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