MASA MAUI Plugin (七)應用通知角標(小紅點)Android+iOS

語言: CN / TW / HK

背景

MAUI的出現,賦予了廣大Net開發者開發多平台應用的能力,MAUI 是Xamarin.Forms演變而來,但是相比Xamarin性能更好,可擴展性更強,結構更簡單。但是MAUI對於平台相關的實現並不完整。所以MASA團隊開展了一個實驗性項目,意在對微軟MAUI的補充和擴展,項目地址**https://github.com/BlazorComponent/MASA.Blazor/tree/feature/Maui/src/Masa.Blazor.Maui.Plugin**,每個功能都有單獨的demo演示項目,考慮到app安裝文件體積(雖然MAUI已經集成裁剪功能,但是該功能對於代碼本身有影響),屆時每一個功能都會以單獨的nuget包的形式提供,方便測試,現在項目才剛剛開始,但是相信很快就會有可以交付的內容啦。

前言

本系列文章面向移動開發小白,從零開始進行平台相關功能開發,演示如何參考平台的官方文檔使用MAUI技術來開發相應功能。

介紹

上一篇文章我們集成了個推的消息通知,那麼消息到達移動端之後,除了會在通知欄顯示之外,在應用的角標也會顯示未讀消息的數量(小紅點),然後用户點擊查看消息之後,這些數字角標也可以自動消除,這個功能在MAUI中如何實現呢。

一、iOS部分

思路

https://developer.apple.com/documentation/uikit/uiapplication/1622918-applicationiconbadgenumber

我們參考一下官方文檔,UIApplication下有一個applicationIconBadgeNumber的屬性

var applicationIconBadgeNumber: Int { get set }

我們只需要給這個屬性賦值具體的整數即可,

https://developer.apple.com/documentation/uikit/uiapplication/1622975-shared

我們可以通過shared獲取當前UIApplication的實例,然後就可以給applicationIconBadgeNumber賦值了,但是如果你直接這樣做,你會發現並沒有效果,因為 iOS 8 以後,需要註冊用户通知,以獲得用户的授權。

https://developer.apple.com/documentation/usernotifications/unusernotificationcenter/1649527-requestauthorization

我們可以通過UNUserNotificationCenterRequestAuthorization方法獲取請求用户本地和遠程的通知權限。 在這裏插入圖片描述

開發步驟

我們新建一個目錄Badger,並在下面新建MAUI類庫項目Masa.Blazor.Maui.Plugin.Badger, 在Platforms下的iOS文件夾新建MasaMauiBadgerService部分類

using UIKit;
using UserNotifications;
namespace Masa.Blazor.Maui.Plugin.Badger
{
	public static partial class MasaMauiBadgerService
	{
        private static void PlatformSetNotificationCount(int count)
		{
			// Requests the user’s authorization to allow local and remote notifications for your app.
			UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Badge, (r, e) =>{});
			
			// The number currently set as the badge of the app icon on the Home screen
			// Set to 0 (zero) to hide the badge number. The default value of this property is 0.
			UIApplication.SharedApplication.ApplicationIconBadgeNumber = count;
		}
	}
}

RequestAuthorization方法有兩個參數

1、UNAuthorizationOptions 代表應用請求的授權選項,這裏我們使用Badge 2、completionHandle 這是一個Action,有兩個參數,第一個參數是一個bool值,代表是否已授予授權,第二個參數是一個NSError類型,表示包含錯誤信息或未發生錯誤的對象。我們這裏暫不處理出錯的情況

我們通過UIApplication.SharedApplication獲取當前的UIApplication實例,然後直接給 ApplicationIconBadgeNumber 賦值,這裏如果我們想清除角標,就直接賦值0即可。 我們繼續在項目根目錄新建MasaMauiBadgerService類,通過SetNotificationCount來調用不同平台的PlatformSetNotificationCount方法。

namespace Masa.Blazor.Maui.Plugin.Badger
{
    // All the code in this file is included in all platforms.
    public static partial class MasaMauiBadgerService
    {
        public static void SetNotificationCount(int count)
        {
            PlatformSetNotificationCount(count);
        }
    }
}

二、安卓部分

思路

安卓部分比iOS相對複雜,我們本着不造輪子的思想,找了一個現成的aar包,ShortcutBadger

項目maven地址:https://repo1.maven.org/maven2/me/leolin/ShortcutBadger

開發步驟

1、我們下載最新的ShortcutBadger-1.1.22.aar包,並新建Android Java 庫綁定項目Masa.Blazor.Maui.Plugin.BadgerBinding 在這裏插入圖片描述

在根目錄創建Jars文件夾,並將下載的aar文件添加進去。添加進去的文件屬性中,生成操作默認選擇的是AndroidLibrary,如果不對請手動更正。 右鍵生成這個項目,這裏很順利沒有任何報錯。

2、我們在Masa.Blazor.Maui.Plugin.Badger項目中引用Masa.Blazor.Maui.Plugin.BadgerBinding項目,由於我們只有在安卓平台需要項目引用,所以我們手動修改一下項目文件中的引用部分,添加Android平台的判斷。

	<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-android'">
	  <ProjectReference Include="..\Masa.Blazor.Maui.Plugin.BadgerBinding\Masa.Blazor.Maui.Plugin.BadgerBinding.csproj" />
	</ItemGroup>

3、從 Android 8.0(API 級別 26)開始,所有通知都必須分配到相應的渠道,關於通知通道的信息,可以參考以下官方文檔

https://developer.android.google.cn/training/notify-user/channels?hl=zh-cn

Java 代碼
    private void createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getString(R.string.channel_name);
            String description = getString(R.string.channel_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.setDescription(description);
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }
    

我們參照以上寫法,在Masa.Blazor.Maui.Plugin.Badger項目的Android平台目錄下新建MasaMauiBadgerService 類,添加一個CreateNotificationChannel方法

using Android.App;
using AndroidX.Core.App;

namespace Masa.Blazor.Maui.Plugin.Badger
{
    // All the code in this file is included in all platforms.
    public static partial class MasaMauiBadgerService
    {
        private static void CreateNotificationChannel()
        {
            if (OperatingSystem.IsAndroidVersionAtLeast(26))
            {
                using var channel = new NotificationChannel($"{Android.App.Application.Context.PackageName}.channel", "Notification channel", NotificationImportance.Default)
                {
                    Description = "Masa notification channel"
                };
                var notificationManager = NotificationManager.FromContext(Android.App.Application.Context);
                notificationManager?.CreateNotificationChannel(channel);
            }
        }
    }
}

1、通過OperatingSystem.IsAndroidVersionAtLeast來判斷當前的Android版本。 2、NotificationChannel的創建方式與Java一致,三個參數分別為ChannelIDnameImportance 這裏注意第三個參數代表重要性級別,我們這裏使用了NotificationImportance.Default

用户可見的重要性級別 重要性(Android 8.0 及更高版本)
緊急:發出提示音,並以浮動通知的形式顯示 IMPORTANCE_HIG
高:發出提示音 IMPORTANCE_DEFAULT
中:無提示音 IMPORTANCE_LOW
低:無提示音,且不會在狀態欄中顯示 IMPORTANCE_MIN

3、Description 指定用户在系統設置中看到的説明。 4、通過NotificationManager.FromContext 創建 notificationManager,然後調用CreateNotificationChannel來創建通知通道。

我們繼續添加SetNotificationCount方法

        private static void PlatformSetNotificationCount(int count)
        {
            ME.Leolin.Shortcutbadger.ShortcutBadger.ApplyCount(Android.App.Application.Context, count);
            NotificationCompat.Builder builder = new(Android.App.Application.Context, $"{Android.App.Application.Context.PackageName}.channel");
            builder.SetNumber(count);
            builder.SetContentTitle(" ");
            builder.SetContentText("");
            builder.SetSmallIcon(Android.Resource.Drawable.SymDefAppIcon);
            var notification = builder.Build();
            var notificationManager = NotificationManager.FromContext(Android.App.Application.Context);
            CreateNotificationChannel();
            notificationManager?.Notify((int)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), notification);
        }

1、調用ShortcutBadgerApplyCount方法來添加角標 2、創建NotificationCompat.Builder示例,並以此設置角標顯示數量(SetNumber),通知的標題(SetContentTitle)和內容(SetContentText),以及通知圖標(SetSmallIcon)。 3、調用我們剛寫好的方法創建通知通道。 4、通過NotificationManager.Notify方法在狀態欄發佈一條通知。 該方法有兩個參數,第一個參數是一個int類型id,這個id是通知的標識符,在應用程序中應該唯一。這裏需要注意:如果你發佈了相同id的通知,並且前一個並沒有取消,那麼該id對應的通知會被更新。第二個參數是一個notification 對象,是通過NotificationCompat.Builder創建出來的。

三、創建Demo項目

1、新建一個MAUI Blazor項目:BadgerSample,添加對Masa.Blazor.Maui.Plugin.Badger項目的引用 2、添加Android權限:修改Android平台目錄中的AndroidManifest.xml文件,添加必要的權限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
	<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
	<uses-permission android:name="android.permission.READ_APP_BADGE" />
	<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" />
</manifest>

注意:國內不同手機廠家可能需要額外的權限配置,需要參考具體廠家的配置説明。

3、修改Index.razor文件

實際的使用場景應該是移動端接收消息推送,在處理消息推送的方法內修改角標,我們這裏為了簡化,在頁面直接通過按鈕觸發修改角標顯示的數量。

@page "/"
@using Masa.Blazor.Maui.Plugin.Badger;

<h1>Masa blazor badger sample</h1>

Masa blazor badger sample.

<button @onclick="OnIncrementClicked">Add</button>
<button @onclick="OnClearClicked">Clear</button>
@code{
	int count;
	private void OnIncrementClicked()
	{
		count++;

		MasaMauiBadgerService.SetNotificationCount(count);
	}
	private void OnClearClicked()
	{
		count = 0;
		MasaMauiBadgerService.SetNotificationCount(count);
	}
}

Android 演示:演示機:vivo x70 pro+

在這裏插入圖片描述

iOS 演示:演示機:iPhone 14 iOS16 模擬器

在這裏插入圖片描述


如果你對我們的 MASA Framework 感興趣,無論是代碼貢獻、使用、提 Issue,歡迎聯繫我們

WeChat:MasaStackTechOps QQ:7424099