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

Xamarin中Firebase与Azure定时通知实现方案咨询

当然可以实现指定时间触发的服药提醒通知!结合你当前用的Xamarin.Forms、Firebase+Azure Notification Hub,再配合原生平台的后台任务/本地通知机制就能搞定,我给你拆解具体的实现步骤和代码示例:

一、Xamarin.Forms 层:处理提醒设置与跨层通信

首先在Forms侧做用户设置界面,让用户输入服药时间、药物名称等信息,之后把这些数据要么存到本地数据库(比如SQLite,方便后续修改/删除),要么通过你已经在用的MessagingCenter推送给原生平台,触发定时任务注册。

举个简单的Forms代码示例:

// 用户保存提醒时的逻辑
var newReminder = new MedicationReminder
{
    Id = Guid.NewGuid().ToString(),
    DrugName = "降压药",
    RemindTime = DateTime.Today.AddHours(8), // 用户选择的时间
    IsRepeat = true // 是否每天重复
};

// 存到本地数据库,方便后续管理
await _localDbService.SaveReminderAsync(newReminder);

// 通过MessagingCenter通知原生平台注册定时任务
MessagingCenter.Send(this, "RegisterMedicationReminder", newReminder);
二、Xamarin.Android 平台:用WorkManager实现可靠定时任务

Android 8+ 对后台服务限制很严,WorkManager是Google官方推荐的后台任务解决方案,能适配不同版本的系统限制,用来做定时提醒非常合适。

步骤1:创建Worker类(处理通知触发逻辑)

[Service]
public class MedicationReminderWorker : Worker
{
    public MedicationReminderWorker(Context context, WorkerParameters @params) : base(context, @params)
    {
    }

    public override Result DoWork()
    {
        // 获取传递的提醒数据
        var reminderId = InputData.GetString("ReminderId");
        var drugName = InputData.GetString("DrugName");

        // 构建本地通知(Android 8+ 需要先创建通知渠道)
        var channelId = "MedicationReminderChannel";
        var notificationManager = NotificationManagerCompat.FromApplicationContext(ApplicationContext);

        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var channel = new NotificationChannel(channelId, "服药提醒", NotificationImportance.High)
            {
                Description = "定时提醒用户按时服药"
            };
            notificationManager.CreateNotificationChannel(channel);
        }

        // 点击通知跳转回应用主页面
        var intent = new Intent(ApplicationContext, typeof(MainActivity));
        var pendingIntent = PendingIntent.GetActivity(ApplicationContext, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);

        var notification = new NotificationCompat.Builder(ApplicationContext, channelId)
            .SetContentTitle("该吃药啦!")
            .SetContentText($"记得服用{drugName}")
            .SetSmallIcon(Resource.Drawable.ic_reminder)
            .SetContentIntent(pendingIntent)
            .SetAutoCancel(true)
            .Build();

        // 触发通知
        notificationManager.Notify(Math.Abs(reminderId.GetHashCode()), notification);

        return Result.Success;
    }
}

步骤2:在MainActivity中接收MessagingCenter消息,注册WorkManager任务

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    // ... 其他初始化代码

    // 订阅MessagingCenter,接收Forms传来的提醒数据
    MessagingCenter.Subscribe<App, MedicationReminder>(this, "RegisterMedicationReminder", (sender, reminder) =>
    {
        // 计算从当前时间到提醒时间的延迟
        var delay = reminder.RemindTime - DateTime.Now;
        // 如果当前时间已过提醒时间,自动设置为明天同一时间
        if (delay.TotalMilliseconds <= 0)
            delay = delay.AddDays(1);

        // 组装传递给Worker的参数
        var inputData = new Data.Builder()
            .PutString("ReminderId", reminder.Id)
            .PutString("DrugName", reminder.DrugName)
            .Build();

        // 创建定时任务:单次触发或重复触发
        WorkRequest workRequest;
        if (reminder.IsRepeat)
        {
            // 每天重复的任务
            workRequest = new PeriodicWorkRequest.Builder(typeof(MedicationReminderWorker), TimeSpan.FromDays(1))
                .SetInitialDelay(delay)
                .SetInputData(inputData)
                .Build();
        }
        else
        {
            // 单次触发的任务
            workRequest = new OneTimeWorkRequest.Builder(typeof(MedicationReminderWorker))
                .SetInitialDelay(delay)
                .SetInputData(inputData)
                .Build();
        }

        // 提交任务到WorkManager
        WorkManager.Instance.Enqueue(workRequest);
    });
}
三、Xamarin.iOS 平台:用UNUserNotificationCenter实现定时本地通知

iOS对后台任务限制更严格,但系统托管的本地通知是实现定时提醒的最优方案,无需后台持续运行,由系统到点触发。

步骤1:在AppDelegate中请求通知权限并处理注册逻辑

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

    // 订阅MessagingCenter,接收Forms传来的提醒数据
    MessagingCenter.Subscribe<App, MedicationReminder>(this, "RegisterMedicationReminder", (sender, reminder) =>
    {
        SetupLocalNotification(reminder);
    });

    return base.FinishedLaunching(app, options);
}

private void SetupLocalNotification(MedicationReminder reminder)
{
    // 构建通知内容
    var content = new UNMutableNotificationContent();
    content.Title = "服药提醒";
    content.Body = $"该服用{reminder.DrugName}了";
    content.Sound = UNNotificationSound.Default;

    // 设置日历触发器,指定提醒的时分
    var dateComponents = new NSDateComponents();
    dateComponents.Hour = reminder.RemindTime.Hour;
    dateComponents.Minute = reminder.RemindTime.Minute;

    // 如果当前时间已过提醒时间,自动顺延到明天
    var now = DateTime.Now;
    if (reminder.RemindTime.TimeOfDay < now.TimeOfDay)
    {
        dateComponents.Day = now.Day + 1;
    }

    // 创建触发器:是否重复(每天同一时间触发)
    var trigger = UNCalendarNotificationTrigger.CreateTrigger(dateComponents, repeats: reminder.IsRepeat);

    // 创建通知请求
    var request = UNNotificationRequest.FromIdentifier(reminder.Id, content, trigger);

    // 添加到系统通知中心
    UNUserNotificationCenter.Current.AddNotificationRequest(request, (error) =>
    {
        if (error != null)
        {
            Console.WriteLine($"注册提醒失败:{error.LocalizedDescription}");
        }
    });
}
四、结合Azure Notification Hub的拓展方案

如果需要跨设备同步提醒(比如用户换手机后,提醒能同步过去),可以把提醒数据存在Firebase或Azure的云端数据库里,然后用Azure Functions做定时触发器,查询到点的提醒记录,再调用Azure Notification Hub的API推送通知。

举个Azure Functions的简单示例:

[FunctionName("SendScheduledReminders")]
public static async Task Run([TimerTrigger("0 */5 * * * *")]TimerInfo timer, ILogger log)
{
    // 查询当前需要触发的提醒记录
    var dueReminders = await _cloudDbService.GetDueRemindersAsync(DateTime.Now);

    foreach (var reminder in dueReminders)
    {
        // 调用Azure Notification Hub推送FCM通知
        var hubClient = NotificationHubClient.CreateClientFromConnectionString("<你的Hub连接字符串>", "<Hub名称>");
        var fcmPayload = $"{{\"notification\":{{\"title\":\"服药提醒\",\"body\":\"该吃{reminder.DrugName}啦!\"}}}}";
        await hubClient.SendFcmNativeNotificationAsync(fcmPayload, reminder.UserId);
    }
}
关键注意事项
  • Android 12+ 要注意电池优化白名单,建议引导用户把应用加入白名单,避免WorkManager任务被系统杀死。
  • iOS 13+ 之后,本地通知的触发必须获得用户授权,一定要在App启动时请求权限。
  • 如果需要修改或删除已有的提醒,记得在原生平台对应的API中取消已注册的任务/通知,避免重复触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:18:05