Android AlarmManager定时调度失效 动态注册Receiver无法接收广播问题
问题修复方案
核心问题原因
- 你构造的是指向
Receiver类的显式广播Intent,而你的Receiver仅做了动态注册、未在Manifest中声明,系统无法识别该组件,导致Alarm触发时广播发送失败。 - 动态注册Receiver时使用的
IntentFilter为空,没有匹配任何广播Action,就算是隐式广播也无法接收。
修复步骤
- 修改广播Intent为隐式Intent,仅指定Action不指定组件类
- 给IntentFilter添加对应Action的匹配规则
- 可选适配高版本系统的权限要求
修复后核心代码
import android.app.AlarmManager import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.os.Build import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.core.content.getSystemService import kotlin.time.ExperimentalTime class Receiver: BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { Log.d("Test", "ACTION: ${intent?.action}") } } @ExperimentalTime class Test: AppCompatActivity() { private val receiver = Receiver() private lateinit var alarmManager: AlarmManager // 自定义广播Action,建议加上应用包名避免和其他应用冲突 private val ACTION_TEST = "com.your.app.package.TEST" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) alarmManager = getSystemService()!! // 给过滤器添加对应Action匹配规则 val filter = IntentFilter(ACTION_TEST) registerReceiver(receiver, filter) // 构造隐式广播Intent,仅指定Action不指定Receiver类 val intent = Intent(ACTION_TEST) val pIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE) val timestamp = System.currentTimeMillis() + 10000 Log.d("Test", "SCHEDULE: $timestamp") // 适配Android 6.0+低电耗模式,需要在空闲状态也触发闹钟可使用setExactAndAllowWhileIdle if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timestamp, pIntent) } else { alarmManager.setExact(AlarmManager.RTC_WAKEUP, timestamp, pIntent) } } override fun onDestroy() { super.onDestroy() unregisterReceiver(receiver) } }
额外适配说明
- 如果运行设备是Android 12(API 31)及以上版本,需要在
AndroidManifest.xml中添加精确闹钟权限声明:<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> - 动态注册的Receiver生命周期和当前Activity绑定,如果Activity被销毁Receiver也会同步注销,闹钟触发时就无法收到广播,如果需要在后台接收广播仍需在Manifest中注册Receiver。
内容的提问来源于stack exchange,提问作者Pascal
相关产品推荐
相关产品推荐

