3

我的目标是:当我调用某个函数时,我想获得确切的当前电池状态(电平、电压等)。

首先,我尝试在我的应用程序中执行此操作,如网站上所示。然后我发现实际上 ACTION_BATTERY_CHANGED 广播是粘性的,这意味着我得到的是上次广播的内容,而不是确切的当前值。

实际上,我已经查看了 android 源代码。对于电池接口,驱动程序具有读取电池内部寄存器的功能,这些寄存器包含当前soc(充电状态)、电压等。

所以我只是想知道系统如何以及何时发送粘性广播 ACTION_BATTERY_CHANGED?它是否定期发送(例如,每 10 秒它会读取电池中的寄存器并发送广播)?或者它是否基于其他标准发送(例如,soc 的变化,电压?但电压会以 mV 为单位频繁变化)?

为了实现我的目标,一种麻烦的方法是实现一个系统调用来调用驱动程序函数,然后重新编译 NDK 以使其在我的应用程序代码中可用。但我只想知道考虑到我上面提到的内容,我是否可以直接通过 ACTION_BATTERY_CHANGED 广播来做到这一点?重新注册广播有影响吗?

4

3 回答 3

2

只需注册广播接收器以获取电池电量。您将在 onReceive 中获得电池电量的结果。

private void batteryLevel() {
         BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
                   public void onReceive(Context context, Intent intent) {
                                context.unregisterReceiver(this);
                                int rawlevel = intent.getIntExtra("level", -1);
                                int scale = intent.getIntExtra("scale", -1);
                                int level = -1;
                                if (rawlevel >= 0 && scale > 0) {
                                                   level = (rawlevel * 100) / scale;
                                }
         batterLevel.setText("Battery Level Remaining: " + level + "%");
     }
    };
IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryLevelReceiver, batteryLevelFilter);
}

希望这会帮助你。

于 2013-06-13T05:09:44.757 回答
1

详细说明 Arpit 的答案,ACTION_BATTERY_CHANGED是一个“粘性”事件——这意味着它不需要接收器来读取它的值。这样您就可以调用 registerReceiver() 并且接收器等于 null,并立即同步读取所有电池统计信息,并且无需取消注册。

这是代码:

private void batteryLevel() {
    IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
    Intent intent = registerReceiver(null, batteryLevelFilter);
    if (intent != null) {
        int rawlevel = intent.getIntExtra("level", -1);
        int scale = intent.getIntExtra("scale", -1);
        int level = -1;
        if (rawlevel >= 0 && scale > 0) {
            level = (rawlevel * 100) / scale;
        }
        batteryLevel.setText("Battery Level Remaining: " + level + "%");
    }
}

此外,在极少数情况下,registerReceiver()可能会引发IllegalArgumentException: regist too many Broadcast Receivers异常,因此您可能希望捕获它以避免崩溃。

于 2017-08-30T22:34:29.333 回答
1

回答问题的:

它是否定期发送(例如,每 10 秒它会读取电池中的寄存器并发送广播)?或者它是否基于其他标准发送(例如,soc 的变化,电压?但电压会以 mV 为单位频繁变化)?

没有唯一的正确答案,Android 不做任何保证,并且因设备而异。

根据我使用不同板子启动的经验,它高度依赖于管理电源的 linux 内核驱动程序。我已经看到它每秒或每 30 秒触发一次 uevents。即使是同一个设备,也会根据它是否连接到电源而以不同的方式启动它。我倾向于看到通常有一些固定的计时器会触发它,另外一些重大事件(例如连接/拆卸充电器)也会触发它。

另请参阅:ACTION_BATTERY_CHANGED 疯狂射击

于 2017-11-17T00:42:27.763 回答