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

如何在Xamarin应用中实现Google Play样式通知(含进度与取消功能)

Xamarin 带下载进度与交互的通知实现方案

由于Xamarin是跨平台框架,Android和iOS的通知系统实现逻辑差异较大,下面分平台说明具体实现方式:


Android 端实现

1. 创建通知通道(Android 8.0+ 必需)

private void CreateDownloadNotificationChannel()
{
    if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
    {
        var channel = new NotificationChannel(
            "DownloadChannel",
            "下载通知",
            NotificationImportance.Default)
        {
            Description = "显示下载进度与操作按钮"
        };
        var notificationManager = (NotificationManager)GetSystemService(NotificationService);
        notificationManager.CreateNotificationChannel(channel);
    }
}

2. 构建带进度条、取消按钮的通知

public Notification BuildDownloadNotification(int progress, string downloadId)
{
    // 点击通知跳转至详情页的意图
    var detailIntent = new Intent(this, typeof(DownloadDetailActivity));
    detailIntent.PutExtra("DownloadId", downloadId);
    var detailPendingIntent = PendingIntent.GetActivity(
        this,
        0,
        detailIntent,
        PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);

    // 取消按钮的触发意图
    var cancelIntent = new Intent(this, typeof(DownloadCancelReceiver));
    cancelIntent.PutExtra("DownloadId", downloadId);
    var cancelPendingIntent = PendingIntent.GetBroadcast(
        this,
        1,
        cancelIntent,
        PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);

    var builder = new NotificationCompat.Builder(this, "DownloadChannel")
        .SetContentTitle("正在下载")
        .SetContentText("文件下载中")
        .SetSmallIcon(Resource.Drawable.ic_download)
        .SetContentIntent(detailPendingIntent)
        .AddAction(Resource.Drawable.ic_cancel, "取消", cancelPendingIntent)
        .SetProgress(100, progress, progress == 0); // progress为0时显示模糊动画进度

    // 添加动画图标(需提前准备AnimatedVectorDrawable资源)
    if (progress == 0)
    {
        var animatedDrawable = Resources.GetDrawable(Resource.Drawable.animated_download, Theme);
        builder.SetLargeIcon(((BitmapDrawable)animatedDrawable).Bitmap);
    }

    return builder.Build();
}

3. 实现取消操作的广播接收器

[BroadcastReceiver(Enabled = true)]
public class DownloadCancelReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        var downloadId = intent.GetStringExtra("DownloadId");
        // 执行取消下载逻辑(比如终止下载任务、更新本地状态)
        var downloadManager = DownloadManager.FromContext(context);
        downloadManager.Remove(long.Parse(downloadId));
        // 关闭通知
        var notificationManager = (NotificationManager)context.GetSystemService(Context.NotificationService);
        notificationManager.Cancel(1); // 1为通知ID,需与创建时保持一致
    }
}

4. 实时更新下载进度

在下载任务的回调方法中调用:

private void UpdateNotificationProgress(int progress, string downloadId)
{
    var notificationManager = (NotificationManager)GetSystemService(NotificationService);
    var notification = BuildDownloadNotification(progress, downloadId);
    notificationManager.Notify(1, notification);
}

iOS 端实现

1. 注册通知权限与交互类别

在AppDelegate的FinishedLaunching方法中初始化:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    // 请求通知权限
    UNUserNotificationCenter.Current.RequestAuthorization(
        UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound,
        (granted, error) =>
        {
            if (granted)
            {
                DispatchQueue.MainQueue.InvokeOnMainThread(() => 
                    UIApplication.SharedApplication.RegisterForRemoteNotifications());
            }
        });

    // 创建带取消按钮的通知类别
    var cancelAction = UNNotificationAction.FromIdentifier(
        "CancelDownload", "取消", UNNotificationActionOptions.None);
    var downloadCategory = UNNotificationCategory.FromIdentifier(
        "DownloadCategory", new[] { cancelAction }, new string[] { }, UNNotificationCategoryOptions.None);
    UNUserNotificationCenter.Current.SetNotificationCategories(new NSSet<UNNotificationCategory>(downloadCategory));

    return true;
}

2. 构建带进度的通知

public void SendDownloadNotification(string downloadId, int progress)
{
    var content = new UNMutableNotificationContent();
    content.Title = progress < 100 ? "正在下载" : "下载完成";
    content.Subtitle = progress < 100 ? "文件下载中" : "文件已就绪";
    content.CategoryIdentifier = "DownloadCategory";
    content.UserInfo = new NSDictionary("DownloadId", downloadId);
    content.Progress = progress / 100.0f;

    // 添加动画附件(支持GIF/本地视频,需传入本地文件路径)
    var gifPath = NSBundle.MainBundle.PathForResource("download_anim", "gif");
    if (!string.IsNullOrEmpty(gifPath))
    {
        var attachment = UNNotificationAttachment.FromIdentifier(
            "anim_attachment", NSUrl.FromFilename(gifPath), null, out var error);
        if (error == null) content.Attachments = new[] { attachment };
    }

    // 立即触发通知
    var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);
    var request = UNNotificationRequest.FromIdentifier(
        $"Download_{downloadId}", content, trigger);
    UNUserNotificationCenter.Current.AddNotificationRequest(request, null);
}

3. 处理通知交互

实现UNUserNotificationCenterDelegate的回调方法:

public override void DidReceiveNotificationResponse(
    UNUserNotificationCenter center, 
    UNNotificationResponse response, 
    Action completionHandler)
{
    var downloadId = response.Notification.Request.Content.UserInfo["DownloadId"].ToString();

    if (response.ActionIdentifier == "CancelDownload")
    {
        // 执行取消下载逻辑
        CancelDownloadTask(downloadId);
        center.RemoveDeliveredNotifications(new[] { response.Notification.Request.Identifier });
    }
    else if (response.ActionIdentifier == UNNotificationDefaultActionIdentifier)
    {
        // 跳转至详情页
        var storyboard = UIStoryboard.FromName("Main", null);
        var detailVC = storyboard.InstantiateViewController(nameof(DownloadDetailVC)) as DownloadDetailVC;
        detailVC.DownloadId = downloadId;
        UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(detailVC, true, null);
    }

    completionHandler();
}

private void CancelDownloadTask(string downloadId)
{
    // 终止下载任务的具体逻辑(比如停止NSURLSession任务)
}

4. 更新下载进度

iOS通知无法直接修改,需删除旧通知后重新发送:

public void UpdateDownloadProgress(string downloadId, int progress)
{
    UNUserNotificationCenter.Current.RemoveDeliveredNotifications(new[] { $"Download_{downloadId}" });
    SendDownloadNotification(downloadId, progress);
}

跨平台统一调用

可以在共享项目中定义接口,通过依赖注入实现跨平台调用:

public interface IDownloadNotificationService
{
    void Initialize();
    void UpdateProgress(string downloadId, int progress);
    void CancelNotification(string downloadId);
}

在Android和iOS项目中分别实现该接口,封装上述原生逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:00:03