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

Kotlin开发Android应用:BroadcastReceiver触发通知失效问题排查

Android BroadcastReceiver 通知推送失效问题排查与修复

我用Kotlin开发一款Android应用,希望在日期变更(DATE_CHANGED)、屏幕点亮(SCREEN_ON)、设备开机完成(BOOT_COMPLETED)时推送通知。尝试用BroadcastReceiver实现,但功能没生效,以下是相关代码:

BroadcastReceiver 实现代码

import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat


class SendNotification: BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_DATE_CHANGED || intent?.action == Intent.ACTION_SCREEN_ON || intent?.action == Intent.ACTION_BOOT_COMPLETED){
            println(intent)
            println(context)
            val hours = TOTKTime.getHours()
            val days = TOTKTime.getDays()
            val notificationManager = context?.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
            val notification = NotificationCompat.Builder(context, "TOTK").setContentText("about ${days}days, ${hours} hours left until TOTK's release").setContentTitle("time until tears of the kingdom").setSmallIcon(R.mipmap.ic_totk).build()
            notificationManager.notify(1, notification)
        }
    }

}

AndroidManifest.xml 配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:name=".app"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_totk_round"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.TOKTTimer"
        tools:targetApi="31">

        <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=".SendNotification" android:exported="false">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.SCREEN_ON" />
                <action android:name="android.intent.action.DATE_CHANGED" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

通知通道初始化代码

import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context

class app: Application() {
    override fun onCreate() {
        super.onCreate()
        val channel = NotificationChannel(
            "TOTK",
            "Time till TOKT",
            NotificationManager.IMPORTANCE_HIGH
        )
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

问题排查与修复方案

1. 静态广播接收限制(Android 8.0+)

Android 8.0(API 26)起,ACTION_SCREEN_ON、ACTION_DATE_CHANGED这类隐式广播无法通过静态注册的BroadcastReceiver接收,系统会直接忽略这类静态注册的广播,只有ACTION_BOOT_COMPLETED属于少数可静态注册的例外,但仍需满足额外条件。

2. 调整SCREEN_ON与DATE_CHANGED的接收方式

这两个广播必须通过动态注册实现:
在Activity或Service中,在合适的生命周期节点(如onResume())注册BroadcastReceiver,onPause()时注销,避免内存泄漏。示例代码如下:

class MainActivity : AppCompatActivity() {
    private lateinit var notificationReceiver: SendNotification

    override fun onResume() {
        super.onResume()
        notificationReceiver = SendNotification()
        val intentFilter = IntentFilter().apply {
            addAction(Intent.ACTION_SCREEN_ON)
            addAction(Intent.ACTION_DATE_CHANGED)
        }
        registerReceiver(notificationReceiver, intentFilter)
    }

    override fun onPause() {
        super.onPause()
        unregisterReceiver(notificationReceiver)
    }
}

3. BOOT_COMPLETED静态注册的注意事项

  • 应用必须至少被用户手动启动过一次,否则系统不会向从未启动的应用发送开机广播。
  • 部分厂商的系统存在后台限制,需手动允许应用的「自启动」权限,否则开机广播可能无法被接收。

4. 其他潜在问题修复

  • NotificationManager获取方式优化:把AppCompatActivity.NOTIFICATION_SERVICE替换为Context.NOTIFICATION_SERVICE,避免上下文类型不匹配导致的异常:
    val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    
  • 动态申请通知权限:Android 13(API 33)及以上版本,需在运行时动态申请POST_NOTIFICATIONS权限,否则通知无法弹出。在MainActivity的onCreate()中添加权限申请逻辑:
    import android.os.Build
    import android.Manifest
    import android.content.pm.PackageManager
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1001)
            }
        }
    }
    
  • 校验业务逻辑:确保TOTKTime类的getHours()和getDays()方法能正常返回有效值,避免因空值或异常导致通知构建失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 06:05:31