如何在Xamarin跨平台中实现应用不在设备最近历史时显示本地通知
嘿,我来帮你搞定这个需求!要在应用完全关闭(甚至不在最近历史列表里)的时候触发本地通知,你当前用的Device.StartTimer肯定不行——这玩意儿只有应用在前台跑的时候才会工作,应用一关掉定时器就歇菜了。咱们得用平台原生的后台调度机制,结合Xamarin.Forms的依赖服务来实现,下面分步骤给你捋清楚:
核心思路
Xamarin.Forms本身没有跨平台的后台定时任务API,所以得针对Android和iOS分别实现原生的调度逻辑,再通过依赖服务统一调用,这样才能在应用关闭时依然触发通知。
步骤1:定义跨平台接口
首先在共享项目里定义一个统一的接口,用来调用不同平台的通知调度功能:
public interface IAlarmScheduler { // 调度重复触发的通知(比如每5分钟一次) void ScheduleRepeatingNotification(TimeSpan interval); // 取消所有已调度的通知 void CancelAllNotifications(); }
步骤2:Android平台实现
Android上我们用AlarmManager实现后台调度,搭配BroadcastReceiver来触发通知。
2.1 创建广播接收器
在Android项目里新建AlarmReceiver.cs:
[BroadcastReceiver(Enabled = true, Exported = true)] [IntentFilter(new[] { "com.yourcompany.yourapp.NOTIFICATION_ALARM" })] public class AlarmReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { // 收到广播后显示本地通知 ShowNotification(context); } private void ShowNotification(Context context) { var notificationManager = NotificationManagerCompat.From(context); // 构建通知内容 var notification = new NotificationCompat.Builder(context, "TIMER_NOTIFICATION_CHANNEL") .SetSmallIcon(Resource.Drawable.ic_notification) .SetContentTitle("定时提醒") .SetContentText("这是应用关闭时触发的通知") .SetPriority(NotificationCompat.PriorityDefault) .Build(); // 显示通知(注意Android 8.0+必须先创建通知通道) notificationManager.Notify(1, notification); } }
2.2 实现调度接口
在Android项目里创建AlarmScheduler.cs:
public class AlarmScheduler : IAlarmScheduler { public void ScheduleRepeatingNotification(TimeSpan interval) { var context = Android.App.Application.Context; var alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService); var intent = new Intent("com.yourcompany.yourapp.NOTIFICATION_ALARM"); var pendingIntent = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable); // Android 12+需要用精确闹钟权限,适配不同版本 if (Build.VERSION.SdkInt >= BuildVersionCodes.S) { alarmManager.SetExactAndAllowWhileIdle(AlarmManager.RtcWakeup, SystemClock.ElapsedRealtime() + interval.TotalMilliseconds, pendingIntent); } else { alarmManager.SetRepeating(AlarmManager.RtcWakeup, SystemClock.ElapsedRealtime() + interval.TotalMilliseconds, interval.TotalMilliseconds, pendingIntent); } } public void CancelAllNotifications() { var context = Android.App.Application.Context; var intent = new Intent("com.yourcompany.yourapp.NOTIFICATION_ALARM"); var pendingIntent = PendingIntent.GetBroadcast(context, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable); var alarmManager = (AlarmManager)context.GetSystemService(Context.AlarmService); alarmManager.Cancel(pendingIntent); } }
2.3 配置权限和通知通道
在AndroidManifest.xml中添加必要权限:
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
然后在MainActivity的OnCreate方法里创建通知通道(Android 8.0+必填):
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel("TIMER_NOTIFICATION_CHANNEL", "定时通知", NotificationImportance.Default) { Description = "应用关闭时的定时提醒通知" }; var notificationManager = GetSystemService(NotificationService) as NotificationManager; notificationManager.CreateNotificationChannel(channel); } }
步骤3:iOS平台实现
iOS上我们用UNUserNotificationCenter结合时间间隔触发器来实现后台通知调度。
3.1 实现调度接口
在iOS项目里创建AlarmScheduler.cs:
public class AlarmScheduler : IAlarmScheduler { public void ScheduleRepeatingNotification(TimeSpan interval) { UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert | UNAuthorizationOptions.Sound, (granted, error) => { if (granted) { var content = new UNMutableNotificationContent(); content.Title = "定时提醒"; content.Body = "这是应用关闭时触发的通知"; content.Sound = UNNotificationSound.Default; // 创建重复触发的时间间隔触发器 var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(interval.TotalSeconds, repeats: true); var request = UNNotificationRequest.FromIdentifier("RepeatingTimerNotification", content, trigger); UNUserNotificationCenter.Current.AddNotificationRequest(request, (error) => { if (error != null) { // 处理通知添加失败的情况 } }); } }); } public void CancelAllNotifications() { UNUserNotificationCenter.Current.RemoveAllPendingNotificationRequests(); } }
3.2 配置iOS权限
在Info.plist中添加通知权限描述:
<key>NSUserNotificationUsageDescription</key> <string>需要发送定时通知提醒您相关事项</string> <key>UIBackgroundModes</key> <array> <string>remote-notification</string> </array>
步骤4:在共享项目中调用
修改你的MainPage.cs,替换原来的Device.StartTimer逻辑,改为调用依赖服务的调度方法:
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); // 调度每5分钟一次的通知 var scheduler = DependencyService.Get<IAlarmScheduler>(); scheduler.ScheduleRepeatingNotification(TimeSpan.FromMinutes(5)); } // 如需取消通知,可调用此方法 private void CancelNotifications() { var scheduler = DependencyService.Get<IAlarmScheduler>(); scheduler.CancelAllNotifications(); } }
关键注意点
- Android 12+需要用户手动开启
SCHEDULE_EXACT_ALARM权限(可以引导用户到应用设置页面开启) - iOS如果用户从最近列表彻底划掉应用,重复通知可能会停止,这是iOS的系统限制,无法绕过
- 测试时一定要把应用完全关闭(从最近列表移除),等待设定的时间看是否触发通知
内容的提问来源于stack exchange,提问作者Swathy
相关产品推荐
相关产品推荐

