You need to enable JavaScript to run this app. 如何基于Kotlin借助广播接收器实现Android电池低于10%的通知提醒
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Kotlin借助广播接收器实现Android电池低于10%的通知提醒

Kotlin实现低电量自动提醒的完整流程

核心链路为:注册系统原生电池状态广播接收器 → 解析广播携带的实时电量值 → 比对是否低于10%阈值 → 触发符合安卓规范的通知提醒,全程无需申请特殊权限,按规范实现即可稳定运行。

前置注意事项
  • 关键提醒:从Android 8.0(API 26)开始,系统屏蔽了绝大多数隐式广播的静态注册渠道,电池状态变化广播就在屏蔽列表中,必须用动态注册的方式在前台可见页面/常驻服务中绑定接收,写在Manifest里的静态注册完全收不到回调。
  • 通知渠道适配:Android 8.0之后所有通知必须关联对应渠道,没有渠道的通知会被系统直接拦截不展示。
  • 通知权限适配:Android 13(API 33)开始,通知属于运行时权限,需要用户手动授权才能弹出。
分步实现代码

1. 初始化低电量通知渠道

建议把这段初始化逻辑放在自定义Application类的onCreate方法中,应用启动时即完成渠道注册,后续发通知可直接复用:

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        initLowBatteryNotifyChannel()
    }

    private fun initLowBatteryNotifyChannel() {
        val channelId = "low_battery_warn"
        // 仅Android 8.0以上需要主动创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val warnChannel = NotificationChannel(
                channelId,
                "低电量提醒",
                NotificationManager.IMPORTANCE_HIGH
            ).apply {
                description = "设备电量低于10%时的提醒通知"
                enableVibration(true)
                vibrationPattern = longArrayOf(100, 200, 100, 200)
            }
            val notifyManager = getSystemService(NotificationManager::class.java)
            notifyManager.createNotificationChannel(warnChannel)
        }
    }
}

2. 编写电池状态广播接收器

这部分为核心处理逻辑,覆盖电量值计算、防重复弹窗、通知构建全流程:

class LowBatteryReceiver : BroadcastReceiver() {
    // 低电量触发阈值
    private val warnThreshold = 10
    // 防重复弹窗标记,避免频繁弹通知引发用户反感
    private var hasWarned = false

    override fun onReceive(context: Context?, intent: Intent?) {
        // 仅处理系统发送的电池状态广播
        if (intent?.action != Intent.ACTION_BATTERY_CHANGED) return
        if (context == null) return

        // 读取广播携带的电量原始数据
        val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
        val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
        // 异常数据直接跳过,避免应用崩溃
        if (level < 0 || scale <= 0) return

        // *注意*:不要直接把EXTRA_LEVEL的原始值当百分比,不同设备电池刻度上限不一致,必须通过比值计算真实电量
        val currentBatteryPercent = (level * 100f / scale).toInt()

        // 满足低电量条件且未发送过提醒时,触发通知
        if (currentBatteryPercent <= warnThreshold && !hasWarned) {
            showWarnNotification(context, currentBatteryPercent)
            hasWarned = true
        }
        // 电量充回阈值以上时重置标记,下次触发阈值可再次提醒
        if (currentBatteryPercent > warnThreshold) {
            hasWarned = false
        }
    }

    private fun showWarnNotification(context: Context, percent: Int) {
        val channelId = "low_battery_warn"
        // 设置通知点击后跳转系统省电设置页
        val clickPendingIntent = PendingIntent.getActivity(
            context,
            0,
            Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS),
            // 适配Android12以上对PendingIntent的强制要求,否则会直接崩溃
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        val notify = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_warn_low_battery) // 替换为项目内的低电量透明矢量图标
            .setContentTitle("电量过低")
            .setContentText("当前设备电量仅剩$percent%,请及时连接充电器")
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setContentIntent(clickPendingIntent)
            .setAutoCancel(true) // 用户点击通知后通知自动消失
            .build()

        // 使用固定通知ID,避免重复弹出多条通知
        NotificationManagerCompat.from(context).notify(1002, notify)
    }
}

3. 动态注册广播接收器

将接收器的注册逻辑绑定在前台Activity中,页面可见时绑定、不可见时解绑,避免内存泄漏:

class MainActivity : AppCompatActivity() {
    private lateinit var lowBatteryReceiver: LowBatteryReceiver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        lowBatteryReceiver = LowBatteryReceiver()
    }

    override fun onResume() {
        super.onResume()
        // 注册接收器,指定需要接收的广播类型
        val batteryFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
        registerReceiver(lowBatteryReceiver, batteryFilter)

        // Android13以上需动态申请通知权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            val notifyPerm = Manifest.permission.POST_NOTIFICATIONS
            if (checkSelfPermission(notifyPerm) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(arrayOf(notifyPerm), 101)
            }
        }
    }

    override fun onPause() {
        super.onPause()
        // 页面不可见时解绑广播,防止内存泄漏
        unregisterReceiver(lowBatteryReceiver)
    }
}
常见踩坑提示
  • 不要将接收器写在Manifest中做静态注册:Android 8.0的隐式广播限制会导致该方式完全收不到回调,调试时会出现无反应的问题
  • 必须加防重复提醒标记:系统的电池状态广播触发频率很高,不加判断会在短时间内弹出几十条重复通知,极易触发系统的骚扰通知拦截
  • 通知小图标需使用透明背景的矢量图,否则在Android 5.0以上系统中会显示为灰色方块,视觉效果极差
  • Android12以上的PendingIntent必须显式指定可变性标记,缺失标记会直接导致应用崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.28 16:45:09