4

When the battery gets low, Android will send an ACTION_BATTERY_LOW intent. Then when it's okay again, it sends ACTION_BATTERY_OKAY.

Unfortunately if my application is started while the battery is low, then I don't get sent the intent; it's not sticky so I can't detect whether a battery alert is currently extant. ACTION_BATTERY_CHANGED is sticky, but it only tells me the current battery charge state, on not whether the system has declared a low battery alert or not.

Is there any way to detect whether the battery is low at any given instant?

David Given
  • 13,277
  • 9
  • 76
  • 123

3 Answers3

2

It's a very tricky question.The related code on Android Developer has a mistake.

Basically, you can learn how to detect it on this link:

https://developer.android.com/training/monitoring-device-state/battery-monitoring.html

You can detect whether it is charging or not charging and low battery or not by a broadcast receiver, using method OnReceive(Context context, Intent intent){}

However, there is a mistake in this link, for monitoring the significant changes.[Notice here, action name is android.intent.action.ACTION_BATTERY_LOW]

[1]

But let's see how it is described in Intent.

ACTION_BATTERY_LOW

Added in API level 1 String ACTION_BATTERY_LOW Broadcast Action: Indicates low battery condition on the device. This broadcast corresponds to the "Low battery warning" system dialog.

This is a protected intent that can only be sent by the system.

Constant Value: "android.intent.action.BATTERY_LOW" You can find this in Android Developers Intent.

In other words, a mistake happens here. It should be action.BATTERY_LOW instead of action.ACTION_BATTERY_LOW.So your code in AndroidManifest should be:

<receiver android:name=".receiver.BatteryLevelReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BATTERY_LOW"/>

            <!--instead of android.intent.action.ACTION_BATTERY_LOW-->
        </intent-filter>
    </receiver>

Also make sure you have your Receiver correct.

public class BatteryLevelReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

        Toast.makeText(context, "BAttery's dying!!", Toast.LENGTH_LONG).show();
        Log.e("", "BATTERY LOW!!");

}

}

It's diffcult to debug or get Log on your laptop, the use of Toast might help.

        Toast.makeText(context, "BAttery's dying!!", Toast.LENGTH_LONG).show();
        //Toast.makeText(Context context, String str, Integer integer).show();

Hopefully it helps to solve you problem.

Mars Gao
  • 69
  • 6
  • This only works if the application is running when the intent is sent. If it gets started while a low battery alert has been declared, I don't receive the intent. – David Given Jul 07 '16 at 12:50
  • I'm sorry...... I'm a little bit confused. But you need to launch your app to get the intent, because it is registered in AndroidManifest in your project. – Mars Gao Jul 08 '16 at 19:57
1

Usually low battery warning appears at 15% , so you can check if the battery level is equal or less than 15%.

Ran
  • 4,117
  • 4
  • 44
  • 70
  • 1
    ...unless the manufacturer changes it, of course. I'll do this if I have to, but I hope I *don't* have to. Thanks, though. – David Given Jun 19 '12 at 16:29
  • 1
    maybe you can read the low level definition. check android source code: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.7_r1/com/android/server/BatteryService.java#BatteryService.0mLowBatteryWarningLevel specifically mLowBatteryWarningLevel = mContext.getResources().getInteger( 128 com.android.internal.R.integer.config_lowBatteryWarningLevel); – Ran Jun 19 '12 at 16:48
  • 1
    That is, unfortunately, private so I don't have access to `com.android.internal`. But the value of the constant is well-defined so I might be able to, hackily, extract it that way. It's evil, though. Plus, from the source code (thanks for the link, BTW), low battery alerts don't quite correspond to the battery level being strictly below 15%. – David Given Jun 20 '12 at 15:49
1

The sticky intent still has some information in it. You should still be able to get the battery level

int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);

float batteryPct = level / (float)scale;

taken from http://developer.android.com/training/monitoring-device-state/battery-monitoring.html

Frank Sposaro
  • 8,511
  • 4
  • 43
  • 64
  • 1
    Yes, but that wasn't what I asked. I don't want to know what the battery level is, I want to know whether the system has declared a low battery alert. That's not the same thing. – David Given Jun 19 '12 at 16:28
  • boolean isLowBattery(float batteryPct) { return batteryPct < 15 ? true : false; } – Frank Sposaro Jun 19 '12 at 17:10
  • 1
    @FrankSposaro I think you misunderstood his question. `15` is a hardcoded number. –  Sep 15 '12 at 02:36
  • @LaiVung What are you talking about? 15 is the number that he wants, but it still doesn't matter because it can be changed to anything. – Frank Sposaro Sep 17 '12 at 21:08
  • @FrankSposaro I hope there would be a method or static field from the framework... I agree that value can be changed, but I'd avoid of hardcoding. –  Sep 18 '12 at 00:44