You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android API 29/33下.NET Maui通知角标不显示,如何解决?

解决Android API29/33下.NET Maui通知角标不显示的问题

核心原因

Android从API29开始没有统一的系统级角标规范,各大厂商(小米、华为、OPPO、vivo等)都有自己的角标实现逻辑,NotificationCompat.Builder.SetNumber()仅能设置通知本身的数字标记,无法直接触发桌面图标角标更新;另外前台服务通知的角标处理逻辑和普通通知也有差异,部分厂商会忽略前台通知的SetNumber值。

具体解决方案

1. 完善通知渠道配置(API26+必做)

首先确保通知渠道正确创建,部分厂商要求渠道开启角标权限才能显示:

// 在应用启动时创建通知渠道(比如MainApplication里)
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
    var channel = new NotificationChannel(MainApplication.ChannelId, "前台服务通知", NotificationImportance.Default)
    {
        Description = "用于显示前台服务运行状态"
    };
    // 开启渠道的角标支持(部分厂商依赖此设置)
    channel.SetShowBadge(true);
    
    var notificationManager = GetSystemService(NotificationService) as NotificationManager;
    notificationManager?.CreateNotificationChannel(channel);
}

2. 适配各大厂商的角标API

直接调用厂商专属接口更新角标,替代仅依赖SetNumber()的方式,以下是主流厂商的适配代码:

public void UpdateAppBadge(int badgeCount)
{
    // 小米
    if (Build.Manufacturer.Equals("Xiaomi", StringComparison.OrdinalIgnoreCase))
    {
        try
        {
            var miuiNotificationClass = Class.ForName("android.app.MiuiNotification");
            var field = miuiNotificationClass.GetDeclaredField("extraNotification");
            var extraNotification = field.Get(null);
            var method = extraNotification.Class.GetDeclaredMethod("setMessageCount", typeof(int));
            method.Invoke(extraNotification, badgeCount);
        }
        catch (Exception)
        {
            // fallback到Intent方式
            var intent = new Intent("android.intent.action.APPLICATION_MESSAGE_UPDATE");
            intent.PutExtra("android.intent.extra.update_application_component_name", PackageName + "/" + PackageManager.GetLaunchIntentForPackage(PackageName).Component.ClassName);
            intent.PutExtra("android.intent.extra.update_application_message_count", badgeCount);
            SendBroadcast(intent);
        }
    }
    // 华为
    else if (Build.Manufacturer.Equals("HUAWEI", StringComparison.OrdinalIgnoreCase))
    {
        try
        {
            var bundle = new Bundle();
            bundle.PutString("package", PackageName);
            bundle.PutString("class", PackageManager.GetLaunchIntentForPackage(PackageName).Component.ClassName);
            bundle.PutInt("badgenumber", badgeCount);
            ContentResolver.Call(Android.Net.Uri.Parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bundle);
        }
        catch (Exception)
        {
            // 忽略异常
        }
    }
    // OPPO
    else if (Build.Manufacturer.Equals("OPPO", StringComparison.OrdinalIgnoreCase))
    {
        try
        {
            var intent = new Intent("com.oppo.unsettledevent");
            intent.PutExtra("pakeageName", PackageName);
            intent.PutExtra("number", badgeCount);
            intent.PutExtra("upgradeNumber", badgeCount);
            if (PackageManager.ResolveActivity(intent, 0) != null)
            {
                SendBroadcast(intent);
            }
            else
            {
                var launcherClass = Class.ForName("com.coloros.launcher.effect.EffectController");
                var method = launcherClass.GetMethod("setBadgeCount", typeof(Context), typeof(String), typeof(int));
                method.Invoke(null, this, PackageName, badgeCount);
            }
        }
        catch (Exception)
        {
            // 忽略异常
        }
    }
    // vivo
    else if (Build.Manufacturer.Equals("vivo", StringComparison.OrdinalIgnoreCase))
    {
        try
        {
            var intent = new Intent("launcher.action.CHANGE_APPLICATION_NOTIFICATION_NUM");
            intent.PutExtra("packageName", PackageName);
            intent.PutExtra("className", PackageManager.GetLaunchIntentForPackage(PackageName).Component.ClassName);
            intent.PutExtra("notificationNum", badgeCount);
            SendBroadcast(intent);
        }
        catch (Exception)
        {
            // 忽略异常
        }
    }
}

3. 前台服务通知的处理

在调用StartForeground()后,单独调用上面的UpdateAppBadge()方法更新角标,而不是依赖通知的SetNumber():

// 构建通知(保留原逻辑,可去掉SetNumber,因为要单独调用厂商API)
notification = new NotificationCompat.Builder(this, MainApplication.ChannelId)
    .SetContentText(input)
    .SetSmallIcon(Resource.Drawable.AppIcon)
    .SetContentIntent(pendingIntent)
    .SetContentTitle("Service Running");

BadgeNumber++;
StartForeground(myId, notification.Build());
// 单独更新角标
UpdateAppBadge(BadgeNumber);

4. 补充必要权限

在AndroidManifest.xml中添加厂商需要的权限:

<!-- 华为角标权限 -->
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
<!-- OPPO角标权限 -->
<uses-permission android:name="com.coloros.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.coloros.launcher.permission.WRITE_SETTINGS" />
<!-- vivo角标权限 -->
<uses-permission android:name="com.vivo.notification.permission.BADGE_ICON" />

关于系统设置选项的说明

Android原生没有统一的「应用图标角标显示数字」设置项,不同厂商的设置入口不同:

  • 小米:设置→应用设置→找到你的应用→通知管理→桌面图标角标
  • 华为:设置→通知→角标设置→找到你的应用
  • OPPO/vivo:设置→通知与状态栏→应用通知管理→找到你的应用→桌面角标

内容的提问来源于stack exchange,提问作者dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:47:09