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

Android AlarmManager无法触发通知问题排查求助

通知无法触发的问题排查与修复

你的代码存在多处关键错误,导致通知无法正常触发,具体问题和修复方案如下:

核心错误点

  • Notification.kt 文件内容完全错误:你提供的Notification.kt实际上是MainActivity的重复代码,正确的应该是继承BroadcastReceiver的接收器类,而非Activity。
  • 全局常量未定义:代码中使用的titleExtra、messageExtra、channelID、notificationID这些常量没有声明,会导致编译或运行错误。
  • PendingIntent 目标类型不匹配:调用PendingIntent.getBroadcast()时,目标类应该是广播接收器,但你传入的是错误的Activity类。
  • 广播接收器未在Manifest注册:自定义的BroadcastReceiver必须在AndroidManifest.xml中注册,否则系统无法识别并触发它。
  • 通知发送逻辑缺失:原代码中没有在广播接收器内构建和发送通知的核心逻辑。

修正后的完整代码

1. 补充MainActivity.kt的常量定义

在MainActivity类外部添加全局常量:

package com.example.firstalarmmanager

import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.AlertDialog
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.firstalarmmanager.databinding.ActivityMainBinding
import java.util.Calendar
import java.util.Date

// 添加全局常量
const val titleExtra = "titleExtra"
const val messageExtra = "messageExtra"
const val channelID = "channelID"
const val notificationID = 101

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?)
    {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        createNotificationChannel()
        binding.submitButton.setOnClickListener { scheduleNotification() }
    }

    @SuppressLint("ScheduleExactAlarm")
    private fun scheduleNotification()
    {
        // 修正Intent目标为广播接收器类
        val intent = Intent(applicationContext, NotificationReceiver::class.java)
        val title = binding.titleET.text.toString()
        val message = binding.messageET.text.toString()
        intent.putExtra(titleExtra, title)
        intent.putExtra(messageExtra, message)

        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext,
            notificationID,
            intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val time = getTime()
        alarmManager.setExactAndAllowWhileIdle(
            AlarmManager.RTC_WAKEUP,
            time,
            pendingIntent
        )
        showAlert(time, title, message)
    }

    private fun showAlert(time: Long, title: String, message: String)
    {
        val date = Date(time)
        val dateFormat = android.text.format.DateFormat.getLongDateFormat(applicationContext)
        val timeFormat = android.text.format.DateFormat.getTimeFormat(applicationContext)

        AlertDialog.Builder(this)
            .setTitle("Notification Scheduled")
            .setMessage(
                "Title: $title\nMessage: $message\nAt: ${dateFormat.format(date)} ${timeFormat.format(date)}"
            )
            .setPositiveButton("Okay"){_,_ ->}
            .show()
    }

    private fun getTime(): Long
    {
        val minute = binding.timePicker.minute
        val hour = binding.timePicker.hour
        val day = binding.datePicker.dayOfMonth
        val month = binding.datePicker.month
        val year = binding.datePicker.year

        val calendar = Calendar.getInstance()
        calendar.set(year, month, day, hour, minute)
        return calendar.timeInMillis
    }

    private fun createNotificationChannel()
    {
        val name = "Notif Channel"
        val desc = "A Description of the Channel"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(channelID, name, importance)
        channel.description = desc
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

2. 创建正确的NotificationReceiver.kt(替换原错误的Notification.kt)

package com.example.firstalarmmanager

import android.app.Notification
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class NotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        context?.let { ctx ->
            val title = intent?.getStringExtra(titleExtra) ?: "Default Title"
            val message = intent?.getStringExtra(messageExtra) ?: "Default Message"

            // 构建通知
            val notification = Notification.Builder(ctx, channelID)
                .setContentTitle(title)
                .setContentText(message)
                .setSmallIcon(R.drawable.ic_notification) // 需替换为你的应用图标
                .setAutoCancel(true)
                .build()

            // 发送通知
            val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.notify(notificationID, notification)
        }
    }
}

3. 在AndroidManifest.xml中注册广播接收器并添加权限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.firstalarmmanager">

    <!-- Android 12+ 需要的精确闹钟权限 -->
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <!-- 唤醒屏幕权限(可选,用于锁屏时显示通知) -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.FirstAlarmManager">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- 注册广播接收器 -->
        <receiver
            android:name=".NotificationReceiver"
            android:exported="false" />
    </application>
</manifest>

额外注意事项

  • 确保你在drawable目录下添加了名为ic_notification的图标资源,或者替换为你已有的图标。
  • 测试时建议设置1分钟后的时间,避免设置过去的时间导致闹钟不触发。
  • 部分厂商系统会限制后台应用的广播触发,可将应用加入系统白名单测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:58:11