AlarmManager仅触发一次且BroadcastReceiver未调用Service问题求助
解决Alarm仅触发一次且服务未被调用的问题
看起来你碰到了两个核心问题:Alarm只执行一次,以及高版本Android中服务无法被后台启动。我来一步步帮你修复这些问题:
1. 修复Alarm仅触发一次的问题
你当前用的AlarmManager.Set()是一次性触发的API,要实现每小时重复执行,得换成重复触发的方法:
适配多版本的重复Alarm设置
替换MainActivity里的Alarm配置代码:
this.context = this; Intent alarmIntent = new Intent(this, typeof(AlarmReceiver)); // 若需要区分多个PendingIntent,requestCode要设为唯一值 var pending = PendingIntent.GetBroadcast(this, 0, alarmIntent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable); var alarmManager = GetSystemService(AlarmService).JavaCast<AlarmManager>(); // 推荐使用不精确重复(更省电,API 19+支持) alarmManager.SetInexactRepeating( AlarmType.ElapsedRealtimeWakeup, // 用Wakeup确保设备休眠时也能触发 SystemClock.ElapsedRealtime() + 5 * 1000, // 首次延迟5秒启动 AlarmManager.IntervalHourly, // 每小时重复一次 pending ); // 若需要精确重复(仅API 19以前有效,API 19后会被系统调整为不精确) // alarmManager.SetRepeating( // AlarmType.ElapsedRealtimeWakeup, // SystemClock.ElapsedRealtime() + 5 * 1000, // 60 * 60 * 1000, // 3600000毫秒 = 1小时 // pending // );
注意点:
- 用
ElapsedRealtimeWakeup而非ElapsedRealtime,确保设备休眠时Alarm也能触发 - 添加
PendingIntentFlags.Immutable(API 31+强制要求),避免PendingIntent被意外篡改
2. 修复服务未被调用的问题
从Android 8.0(API 26)开始,系统严格限制后台启动服务的行为,直接调用StartService()会抛出IllegalStateException,需要改用前台服务:
修改AlarmReceiver的服务启动逻辑
[BroadcastReceiver] [IntentFilter(new[] { Intent.ActionBootCompleted })] // 可选:添加开机自启支持 public class AlarmReceiver : BroadcastReceiver { public override void OnReceive(Context context, Intent intent) { Toast.MakeText(context, "Received intent!", ToastLength.Short).Show(); Intent not = new Intent(context, typeof(Services.NotifcationService)); if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { // API 26+必须使用StartForegroundService启动服务 context.StartForegroundService(not); } else { // 低版本用StartService context.StartService(not); } } }
将NotificationService改造为前台服务
API 26+要求前台服务必须显示通知,否则系统会在几秒内终止服务,修改你的服务代码:
using System; using Android.App; using Android.Content; using Android.OS; namespace example.Services { [Service(Label = "NotificationService")] [IntentFilter(new String[] { "com.example.NotificationService" })] public class NotificationService : Service { IBinder binder; private const int NOTIFICATION_ID = 1; private const string CHANNEL_ID = "ForegroundServiceChannel"; public override void OnCreate() { base.OnCreate(); // 创建通知渠道(API 26+必需) CreateNotificationChannel(); } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { // 构建前台通知 Notification notification = new Notification.Builder(this, CHANNEL_ID) .SetSmallIcon(Resource.Drawable.logoArrow) .SetContentTitle("Foreground Service Running") .SetContentText("Your notification service is active") .SetPriority(NotificationPriority.High) .Build(); // 将服务设为前台服务 StartForeground(NOTIFICATION_ID, notification); // 执行你的业务逻辑:发送本地通知 SendLocalNotification(); // 返回Sticky确保服务被杀死后可重启(根据需求调整) return StartCommandResult.Sticky; } private void SendLocalNotification() { var notificationManager = (NotificationManager)GetSystemService(NotificationService); Notification.Builder notifyBuilder = new Notification.Builder(this, CHANNEL_ID) .SetSmallIcon(Resource.Drawable.logoArrow) .SetContentTitle("Sample Notification") .SetContentText("Hello World! This is my first notification") .SetPriority(NotificationPriority.Default) .Build(); notificationManager.Notify(2, notifyBuilder.Build()); // 用不同ID避免覆盖前台通知 } private void CreateNotificationChannel() { if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel(CHANNEL_ID, "Foreground Service Channel", NotificationImportance.Default) { Description = "Channel for foreground service notifications" }; var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.CreateNotificationChannel(channel); } } public override IBinder OnBind(Intent intent) { binder = new NotificationServiceBinder(this); return binder; } } public class NotificationServiceBinder : Binder { readonly NotificationService service; public NotificationServiceBinder(NotificationService service) { this.service = service; } public NotificationService GetNotificationService() { return service; } } }
3. 检查Manifest配置
确保已添加必要权限和组件声明:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application ...> <receiver android:name=".AlarmReceiver" /> <service android:name=".Services.NotificationService" /> </application>
额外提示
- Android 12(API 31)及以上,若需要精确Alarm,需申请
SCHEDULE_EXACT_ALARM权限并动态请求 - 长期重复任务更推荐使用WorkManager,它能更好适配系统省电策略,尤其是Android 12+环境
内容的提问来源于stack exchange,提问作者Gurpreet Bhopal
相关产品推荐
相关产品推荐

