3

My goal is : when I call some function, I want to get the exact current battery status(level,voltage and etc..).

First I tried to do it in my application as shown on the website. Then I have found actually the ACTION_BATTERY_CHANGED broadcast is sticky which means what I got is from last broadcast, not the exact current value.

Actually, I have looked into the android source code. For the battery interface, the driver has functions to read the registers inside the battery which contain the current soc(state of charge), voltage and etc..

So I am just wondering how and when the system sends the sticky broadcast ACTION_BATTERY_CHANGED? Does it send it periodically(e.g.,every 10 seconds it will read the registers in battery and send the broadcast)? Or does it send based on other criteria(e.g, change of soc, voltage? But voltage will change so frequently in terms of mV)?

To realize my goal, one troublesome way is to implement a system call to call the driver functions and then recompile the NDK to make it usable in my application code. But I just want to know whether I can do this directly through the ACTION_BATTERY_CHANGED broadcast considering what I have mentioned above? Does registering the broadcast again have any effect?

Community
  • 1
  • 1
Hao Shen
  • 2,605
  • 3
  • 37
  • 68

3 Answers3

2

Simply register the Broadcast receiver for the battery level. You will get the result of battery level in 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);
}

Hope this will help you.

Arpit Patel
  • 1,561
  • 13
  • 23
  • Hi,thanks. So the point is to unregister the receiver and register it again every time? But I think if the android system does not broadcast the new battery level value, no matter how often I call the batteryLevel() function, I will still get the value last broadcasted. Is that right? – Hao Shen Jun 13 '13 at 05:26
  • yes by this way you just have to unregister it after getting the value and it register that using this method again when you call this method. – Arpit Patel Jun 13 '13 at 05:32
1

To elaborate on the answer from Arpit, ACTION_BATTERY_CHANGED is a "sticky" event - which means it doesn't need a receiver to be able to read its values. That way you may call registerReceiver() with receiver equal to null, and read all the battery stats synchronously right away, and there's no need to unregister.

Here's the code:

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 + "%");
    }
}

Also, in some rare cases, registerReceiver() may throw an IllegalArgumentException: regist too many Broadcast Receivers exception, so you may want to catch it to avoid crashing.

Toastrackenigma
  • 7,604
  • 4
  • 45
  • 55
john316
  • 306
  • 1
  • 8
1

In response to the of the question:

Does it send it periodically(e.g.,every 10 seconds it will read the registers in battery and send the broadcast)? Or does it send based on other criteria(e.g, change of soc, voltage? But voltage will change so frequently in terms of mV)?

There is no single correct answer, Android makes no guarantees and it varies by device.

Based on my experience working with different board bring-ups it is highly dependant on the linux kernel drivers managing power. I've seen it firing uevents off once per second or once every 30 seconds. Even the same device will fire it differently based on whether it is attached to a power source or not. I tend to see that usually there is some fixed timer that triggers it and additionally major events such as attaching/detaching a charger will trigger it as well.

Also see: ACTION_BATTERY_CHANGED firing like crazy

satur9nine
  • 13,927
  • 5
  • 80
  • 123