Get battery level before broadcast receiver responds for Intent.ACTION_BATTERY_CHANGED

32,560

Solution 1

Is there a way to nudge this to get it working or simply run some code to see what the battery level was on the last broadcast?

You can call registerReceiver() with your IntentFilter and a null BroadcastReceiver to get the last-broadcast Intent. This works because ACTION_BATTERY_CHANGED is a so-called "sticky broadcast", which I describe a bit more in this StackOverflow question-and-answer.

Solution 2

This is how to get the battery level without registering a receiver:

Intent batteryIntent = context.getApplicationContext().registerReceiver(null,
                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int rawlevel = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
double scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
double level = -1;
if (rawlevel >= 0 && scale > 0) {
    level = rawlevel / scale;
}

It can use a null BroadcastReceiver because of the sticky nature of the broadcast.

It uses the getApplicationContext() trick in case you are in a intent receiver and get the exception:

android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents

Solution 3

    public static String batteryLevel(Context context)
    {
        Intent intent  = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));   
        int    level   = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
        int    scale   = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
        int    percent = (level*100)/scale;
        return String.valueOf(percent) + "%";
    }

Solution 4

// Put this Code into your MainActivity

private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context c, Intent i) {
        int level = i.getIntExtra("level", 0);
        ProgressBar pb = (ProgressBar) findViewById(R.id.progressbar);
        pb.setProgress(level);
        TextView tv = (TextView) findViewById(R.id.textfield);
        tv.setText("Battery Level: " + Integer.toString(level) + "%");
    }

};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    registerReceiver(mBatInfoReceiver, new IntentFilter(
            Intent.ACTION_BATTERY_CHANGED));
}

Solution 5

I use this method to get the battery level without receiving updates.

public float getMyBatteryLevel() {
        Intent batteryIntent = this.getApplicationContext().registerReceiver(null,
        new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        return batteryIntent.getIntExtra("level", -1);
}
Share:
32,560
stealthcopter
Author by

stealthcopter

Creator of Nexus Revamped Live Wallpaper

Updated on July 09, 2022

Comments

  • stealthcopter
    stealthcopter almost 2 years

    I have a broadcast receiver in my program to get react to the battery level like so:

    private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver(){
        @Override
        public void onReceive(Context arg0, Intent intent) {
            int level = intent.getIntExtra("level", 0);
            // do something...
        }
    }
    
        registerReceiver(this.mBatInfoReceiver, 
                new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
    

    However this code has to wait for the battery status to be updated so if you have a GUI element that needs to be set based on the battery level it must wait for a battery event to occur. Is there a way to nudge this to get it working or simply run some code to see what the battery level was on the last broadcast?

  • stealthcopter
    stealthcopter over 13 years
    The receiver I have in the question actually is called as soon as it is created I just didn't notice because I reinitialised the variables after it.
  • Cheryl Simon
    Cheryl Simon over 13 years
    Will getting the applicationContext as described below to make this call cause problems? I have the problem that my broadcast receiver isn't allowed to register for intents, even though I pass in null. What is the correct solution to this problem?
  • CommonsWare
    CommonsWare over 13 years
    @Mayra: getApplicationContext() should be fine here, particularly if you are trying to do this from a BroadcastReceiver.
  • hemisphire
    hemisphire over 12 years
    Under certain situations (like running in a system service), getApplicationContext() will return null. In that case the call should be: context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
  • Tom
    Tom about 12 years
    @hemisphire wrote "Under certain situations (like running in a system service), getApplicationContext() will return null". I don't think that's always true. Perhaps it depends on the type of service.
  • thecr0w
    thecr0w almost 12 years
    Perfect! I can do it without service now.
  • Xanatos
    Xanatos about 10 years
    I'm pretty sure that this is the only way to get access the battery info from within a BroadcastReceiver without getting a ReceiverCallNotAllowedException. Thanks for a useful tip! :)
  • user3233280
    user3233280 over 9 years
    may i need to unresgiter this reciever as well in onPause i m unregistering but this is creating error 01-11 15:08:21.711: E/AndroidRuntime(31730): Caused by: java.lang.IllegalArgumentException: Receiver not registered: com.example.batterylevel.ChargeActivity$1@426304a0