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

应用退出最近列表后,ACTION_BATTERY_CHANGED广播接收器失效问题

解决Android应用完全退出后无法监听电池电量变化的问题

你的问题根源在于动态注册的BroadcastReceiver和Activity生命周期绑定——当应用完全退出,MainActivity被销毁时,这个接收器也会被系统自动注销(如果没手动注销还会引发内存泄漏),自然就收不到ACTION_BATTERY_CHANGED广播了。而且要注意,ACTION_BATTERY_CHANGED是系统特殊广播,不支持静态注册(在AndroidManifest.xml中声明接收器无效),所以得换个方案:用**前台服务(Foreground Service)**来托管广播接收器,让它在后台持续运行监听电量变化。

下面是具体的实现步骤和代码:

1. 创建前台服务托管广播接收器

前台服务的优先级更高,不容易被系统回收,而且从Android 8.0开始,后台服务会被限制,前台服务必须显示一个状态栏通知(这是系统强制要求)。

public class BatteryMonitorService extends Service {
    private BroadcastReceiver mBatInfoReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        // 注册电池电量变化广播接收器
        IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        mBatInfoReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                int batteryLevel = intent.getIntExtra("level", 0);
                Toast.makeText(context, "当前电量:" + batteryLevel + "%", Toast.LENGTH_SHORT).show();
            }
        };
        registerReceiver(mBatInfoReceiver, batteryFilter);

        // 初始化前台服务通知(Android 8.0+必填)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建通知渠道
            NotificationChannel channel = new NotificationChannel(
                "battery_monitor_channel",
                "电池监控",
                NotificationManager.IMPORTANCE_LOW
            );
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);

            // 构建通知
            Notification notification = new NotificationCompat.Builder(this, "battery_monitor_channel")
                .setSmallIcon(R.drawable.ic_battery) // 替换成你的应用图标
                .setContentTitle("电池监控中")
                .setContentText("正在监听电量变化")
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .build();

            // 启动前台服务
            startForeground(1, notification);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 注销接收器,避免内存泄漏
        if (mBatInfoReceiver != null) {
            unregisterReceiver(mBatInfoReceiver);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null; // 不需要绑定服务,返回null即可
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 服务被系统杀死后尝试自动重启
        return START_STICKY;
    }
}

2. 配置Manifest权限和服务声明

在AndroidManifest.xml中添加必要的权限和服务声明:

<!-- 前台服务权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 13及以上需要通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application ...>
    <!-- 声明电池监控服务 -->
    <service
        android:name=".BatteryMonitorService"
        android:foregroundServiceType="dataSync" /> <!-- 指定服务类型,优化系统调度 -->
    ...
</application>

3. 在Activity中启动前台服务

在你的MainActivity中启动服务,同时处理Android 13+的通知权限请求:

public class MainActivity extends AppCompatActivity {
    private static final int NOTIFICATION_PERMISSION_REQUEST_CODE = 1001;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 处理Android 13+的通知权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(
                    new String[]{Manifest.permission.POST_NOTIFICATIONS},
                    NOTIFICATION_PERMISSION_REQUEST_CODE
                );
            } else {
                startBatteryMonitorService();
            }
        } else {
            startBatteryMonitorService();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == NOTIFICATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startBatteryMonitorService();
            } else {
                // 用户拒绝权限,提示无法正常监控电池
                Toast.makeText(this, "需要通知权限才能启动电池监控", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void startBatteryMonitorService() {
        Intent serviceIntent = new Intent(this, BatteryMonitorService.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(serviceIntent);
        } else {
            startService(serviceIntent);
        }
    }
}

注意事项

  • 前台服务会在状态栏显示一个持续通知,这是系统强制要求,无法隐藏(除非你的应用拥有特殊系统权限)。
  • 当不需要监控电量时,记得调用stopService()或在Service中调用stopSelf()来停止服务,避免浪费资源。
  • START_STICKY返回值可以让服务在被系统回收后尝试重启,但不能保证100%重启,系统资源极度紧张时还是会被彻底杀死。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:20:40