3

I'm stuck with a little problem here.

I want my app to do something, but only when the battery is at 10%.

My app doesn't watch the battery level constantly; it just waits for a LOW_BATTERY intent.

It works if i don't specify a level, but it works 3 times: 15%, 10%, and 5%

I only want it to do something at 10%.

Here is my code :

public void onReceive(Context context, Intent intent) 
{
    if(intent.getAction().equals(ACTION_BATTERY_LOW))
    {
        int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
        int percent = (level*100)/scale; 

        if(percent == 10)
        {
            // Do Something

        }
    }
}
jimmym715
  • 1,512
  • 1
  • 16
  • 25
FrenchDude
  • 57
  • 1
  • 8
  • 2
    I have never worked with the battery level, but why not accept the three notifications, test the level of the battery in each notification and only act when it is 10%? – Sam Apr 24 '12 at 22:18
  • 2
    In addition to Sam's comment, bear in mind that there is no guarantee that you will ever get a broadcast for exactly 10%. A particular device could easily broadcast at 11% and then again at 9%. – CommonsWare Apr 24 '12 at 22:25
  • To Sam : Hey, this is exactly what i do ! I get the notification about the low battery, and then i check if it is 10%, then i do something. But it never works. Maybe be as CommonsWare suggested i should try to also accept 9 an 11 %. I'll tell you ! Thanks ! ;) – FrenchDude Apr 24 '12 at 22:27
  • It does not work ! I even tried "if(percent>8 && percent<12)". Can someone help me ? – FrenchDude Apr 24 '12 at 22:40
  • Just check what percentage you DO get, and not just go "it no work". If your retrieval of the percentage is bad and you get weird numbers, then that's your problem. If you get poked only at 7.8%, there you are. Just debug and write the percentage somewhere? Then, if you did fire your event, make sure you set some sort of flag that it doesn't do it twice? – Nanne Jun 06 '12 at 07:45

2 Answers2

6

ACTION_BATTERY_LOW doesn't have the Extras you're trying to read from it, so you're getting percent as -1 every time.

As @bimal hinted at, those Extras are attached to the ACTION_BATTERY_CHANGED Broadcast. That doesn't mean, however, that you should just register to receive that instead. ACTION_BATTERY_CHANGED is sticky, so registerReceiver() returns the last Intent immediately. That means you can do something like:

public void onReceive(Context context, Intent intent) {
    if(intent.getAction().equals(ACTION_BATTERY_LOW)) {
        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryStatus = context.registerReceiver(null, ifilter);

        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
        int percent = (level*100)/scale; 

        if (percent <= 10 && percent > 5) {
            // Do Something
        }
    }
}

Note that registerReciever() was called with a null BroadcastReceiver, so you don't have to worry about unregistering. This is a nice, clean way to just say "What is the battery status right now?" (Well, technically, it's what was it last time a Broadcast was sent.)

Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
  • Thanks for this. But now how can i make sure that i only perform the "do something" once, and only once, until the next time it get low ? – FrenchDude Jul 06 '12 at 18:06
  • @user1352526 That's a different question, but simple enough: `ACTION_BATTERY_OKAY` is specifically there to let you know when the battery is no longer "low". So 1) register for that Broadcast, too, 2) set a flag indicating that "this low state has been handled" when you do your something in response to the LOW state, 3) when you get the LOW Broadcast, ignore it if it's already been handled, and 4) clear that flag when you get the OKAY Broadcast. – Darshan Rivka Whittle Jul 06 '12 at 20:46
  • Thank you very much i'll look after that. This could be useful – FrenchDude Jul 07 '12 at 09:28
  • But i am wondering... What is the broadcast that i should expect to go in your "onReceive" ? – FrenchDude Jul 11 '12 at 16:54
  • @user1352526 You can register to receive both `ACTION_BATTERY_LOW` and `ACTION_BATTERY_OKAY` with that same one; that's what the `if(intent.getAction().equals(ACTION_BATTERY_LOW))` is for -- so you can tell which Broadcast you've just received and respond accordingly. You likely want `else if(intent.getAction().equals(ACTION_BATTERY_OKAY))` below it, were the logic for the OKAY Broadcast goes. – Darshan Rivka Whittle Jul 11 '12 at 18:08
3

In this case, you can use "ACTION_BATTERY_CHANGED"

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
            int level = intent.getIntExtra("level", 0);
            int scale = intent.getIntExtra("scale", 100);
            double batStatus = level * 100 / scale;
        }
    }

Hope this will help you.

bimal
  • 41
  • 1
  • 2
  • 7