Android Kotlin实现低电量弹窗、插电自动关闭弹窗的开发问题咨询
功能需求
- 设备电量低于20%时弹出低电量提示对话框
- 设备连接充电器时展示对应提示对话框,无需用户点击操作即可自动关闭
- 设备断开充电器时若电量低于20%重新弹出低电量提示
现有代码问题
- 每次调用对话框方法都会重新 inflate 布局、创建新的 Dialog 实例,全局持有 dialog 引用失效,无法正常关闭已弹出的对话框
- 仅监听了充电插拔广播,未监听电量变化广播,电量自然掉到20%以下时无法触发提示
- 连接充电器时的自动关闭逻辑未实现
- 对话框 show 判断逻辑错误,原代码写的是
if(d.isShowing) d.show(),刚好写反了
完整修正实现
1. BaseActivity.kt 代码修正
open class BaseActivity : AppCompatActivity() { // 全局复用Dialog实例 private var batteryDialog: AlertDialog? = null private val autoDismissDelay = 3000L // 充电提示自动关闭时长3秒 /** * 展示电量相关对话框 * @param show 是否展示 * @param message 对话框提示文案 * @param autoDismiss 是否需要自动关闭 */ fun showBatteryDialog(show: Boolean, message: String, autoDismiss: Boolean = false) { if (show) { // 已显示的话只更新文案即可 if (batteryDialog?.isShowing == true) { batteryDialog?.findViewById<TextView>(R.id.txtViewDescription)?.text = message } else { // 首次创建 val dialogView = layoutInflater.inflate(R.layout.dialog_battery_low, null) batteryDialog = AlertDialog.Builder(this@BaseActivity) .setView(dialogView) .setCancelable(false) .create() batteryDialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) dialogView.txtViewDescription.text = message dialogView.txtViewOk.setOnClickListener { finishAffinity() } batteryDialog?.show() } // 需要自动关闭的话发延迟任务 if (autoDismiss) { batteryDialog?.window?.decorView?.postDelayed({ dismissBatteryDialog() }, autoDismissDelay) } } else { dismissBatteryDialog() } } /** * 关闭电量对话框 */ fun dismissBatteryDialog() { batteryDialog?.takeIf { it.isShowing }?.dismiss() batteryDialog = null } override fun onDestroy() { super.onDestroy() // 页面销毁时关闭对话框避免内存泄漏 dismissBatteryDialog() } }
2. MainActivity.kt 广播相关代码修正
class MainActivity : BaseActivity() { private val mBatteryReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val bm = context.getSystemService(Application.BATTERY_SERVICE) as BatteryManager val batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) when (intent.action) { // 充电连接 Intent.ACTION_POWER_CONNECTED -> { Toast.makeText(context, "Power connected", Toast.LENGTH_SHORT).show() showBatteryDialog( show = true, message = "充电器已连接", autoDismiss = true ) } // 充电断开 Intent.ACTION_POWER_DISCONNECTED -> { Toast.makeText(context, "Power disconnected", Toast.LENGTH_SHORT).show() if (batLevel < 20) { showBatteryDialog( show = true, message = "您的手机电量过低" ) } else { dismissBatteryDialog() } } // 电量变化 Intent.ACTION_BATTERY_CHANGED -> { // 未充电且电量低于20%才弹低电量提示 val isCharging = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) == BatteryManager.BATTERY_STATUS_CHARGING if (!isCharging && batLevel < 20) { showBatteryDialog( show = true, message = "您的手机电量过低" ) } else if (batLevel >= 20) { dismissBatteryDialog() } } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 动态注册广播 val filter = IntentFilter().apply { addAction(Intent.ACTION_POWER_CONNECTED) addAction(Intent.ACTION_POWER_DISCONNECTED) addAction(Intent.ACTION_BATTERY_CHANGED) } registerReceiver(mBatteryReceiver, filter) } override fun onDestroy() { super.onDestroy() // 解绑广播避免内存泄漏 unregisterReceiver(mBatteryReceiver) } }
关键优化点
- 全局复用同一个Dialog实例,避免创建多个实例导致无法正常关闭
- 新增电量变化广播监听,覆盖电量自然耗到阈值的场景
- 新增自动关闭逻辑,充电连接的提示3秒后自动消失
- 修复原代码对话框显示判断逻辑错误的问题
- 增加页面销毁时的资源回收逻辑,避免内存泄漏
内容的提问来源于stack exchange,提问作者Piyush Savalia
相关产品推荐
相关产品推荐

