#主要问题表现:我在设置闹钟后,应用在不退出的情况下正常唤醒,应用在退出时无法唤醒.麻烦各位帮忙看下
注册代码:
<!-- 服务声明 -->
<service
android:name=".service.AlarmJobService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" />
<!-- 广播接收器 -->
<receiver android:name=".work.AlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<!-- 针对中国厂商的特殊声明 -->
<uses-permission android:name="com.xiaomi.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="com.huawei.permission.SCHEDULE_EXACT_ALARM"/>
调用代码:
class AlarmClockActivity : BaseActivity() {
override fun getLayoutResId(): Int {
return R.layout.act_alarm_clock
}
override fun initActivity() {
checkExactAlarmPermission()
scheduleAlarm()
}
// TODO: 2025/12/2 16:03 -(Administrator)-{🎉 内部调用}
private fun checkExactAlarmPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
if (!alarmManager.canScheduleExactAlarms()) {
// 请求SCHEDULE_EXACT_ALARM权限
startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
}
}
}
private fun scheduleAlarm() {
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 12)
set(Calendar.MINUTE, 0)
}
// 确保时间在未来
var triggerTime = calendar.timeInMillis
if (triggerTime <= System.currentTimeMillis()) {
triggerTime += 24 * 60 * 60 * 1000 // 推迟到第二天
}
// 方案1: 使用JobScheduler
scheduleWithJobScheduler(triggerTime)
// 方案2: 使用AlarmManager作为备用
scheduleWithAlarmManager(triggerTime)
}
private fun scheduleWithJobScheduler(triggerTime: Long) {
try {
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
val componentName = ComponentName(this, AlarmJobService::class.java)
val delay = triggerTime - System.currentTimeMillis()
val jobInfo = JobInfo.Builder(0, componentName)
.setMinimumLatency(delay)
.setOverrideDeadline(delay + 1000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
.setPersisted(true)
.build()
val result = jobScheduler.schedule(jobInfo)
if (result == JobScheduler.RESULT_SUCCESS) {
Log.d("AlarmClockActivity", "Job scheduled successfully")
} else {
Log.e("AlarmClockActivity", "Job scheduling failed")
// 失败时回退到AlarmManager
scheduleWithAlarmManager(triggerTime)
}
} catch (e: Exception) {
Log.e("AlarmClockActivity", "JobScheduler error", e)
scheduleWithAlarmManager(triggerTime)
}
}
private fun scheduleWithAlarmManager(triggerTime: Long) {
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
triggerTime,
pendingIntent
)
} else {
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTime,
pendingIntent
)
}
Log.d("AlarmClockActivity", "Alarm scheduled with AlarmManager")
}
// TODO: 2025/12/2 16:13 -(Administrator)-{🎉 全局调用}
companion object {
fun startActivity(context: Context) {
val intent = Intent(context, AlarmClockActivity::class.java)
context.startActivity(intent)
}
}
}
服务代码:
class AlarmJobService : JobService(){
override fun onStartJob(params: JobParameters?): Boolean {
showNotification()
return false
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
private fun showNotification() {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"alarm_channel",
"Alarm Notifications",
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(this, "alarm_channel")
.setContentTitle("闹钟")
.setContentText("时间到了!")
.setSmallIcon(R.mipmap.app_icon_naozhou)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
.build()
notificationManager.notify(1, notification)
}
}
接受器代码:
class AlarmReceiver : BroadcastReceiver(){
@SuppressLint("ScheduleExactAlarm")
override fun onReceive(context: Context, intent: Intent?) {
when (intent?.action) {
Intent.ACTION_BOOT_COMPLETED -> {
// 设备重启后重新设置闹钟
val prefs = context.getSharedPreferences("alarm_prefs", Context.MODE_PRIVATE)
val triggerTime = prefs.getLong("next_alarm_time", 0)
if (triggerTime > 0) {
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager
val alarmIntent = Intent(context, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
context,
0,
alarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
triggerTime,
pendingIntent
)
} else {
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTime,
pendingIntent
)
}
}catch (e : Exception){
e.printStackTrace()
}
}
}
else -> {
// 处理闹钟触发
val serviceIntent = Intent(context, AlarmJobService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent)
} else {
context.startService(serviceIntent)
}
}
}
}
}