Does action_battery_low
allow being fired from the manifest because I thought it did?
Here is my manifest for it:
<reciever android:name=".BatteryReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BATTERY_LOW"/>
</intent-filter>
</reciever>
But it never gets fired when I get the low battery warning from the system. Can this only be fired explicitly?
The original question states that the receiver does not receive intents. This is because the receiver was declared as <reciever>
rather than <receiver>
. Had the receiver element been declared correctly, it would have worked.
Another major source of confusion is the fact that the Android documentation incorrectly references "android.intent.action.ACTION_BATTERY_LOW"
and "android.intent.action.ACTION_BATTERY_OKAY"
. There is an existing Android Issue for this documentation error, but you should be aware that some of the comments on that issue are misleading.
Instead, the receiver's actions must be "android.intent.action.BATTERY_LOW"
and "android.intent.action.BATTERY_OKAY"
. When referencing these actions from Java source, you may use the constants android.content.Intent.ACTION_BATTERY_LOW and android.content.Intent.ACTION_BATTERY_OKAY which are defined correctly.
Unfortunately Reto Meier also incorrectly defines the action in A Deep Dive Into Location. An issue has been filed for this as well.
From my own testing, I ran into the same issue and solution as GeoBio Boo
But then I took a closer look at my code and noticed that I was filtering on the action android.intent.action.ACTION_BATTERY_LOW as described in the docs: https://developer.android.com/training/monitoring-device-state/battery-monitoring.html
In reality, the action is android.intent.action.BATTERY_LOW (no ACTION_). Once I made this change, I was able to register the receiver in the Manifest and receive the event successfully (tested through emulator's power capacity command)
You need to programatically register for ACTION_BATTERY_LOW
. I spent a very long time trying to figure this out, and realized that registering it in the AndroidManifest.xml
does not work.
In other words, in your onResume() or onCreate() call:
registerReceiver(receiver, new IntentFilter(Intent.ACTION_BATTERY_LOW));
You do NOT need the BATTERY_STATS
permission.
Disregard the permission suggestion in this answer, it is incorrect.
You might have request permission in order to catch the BATTERY_LOW
action.
Try adding <uses-permission android:name="android.permission.BATTERY_STATS"/>
to your manifest.
Also, you can place multiple actions within the same intent-filter such as:
<reciever android:name=".BatteryReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.BATTERY_LOW"/>
</intent-filter>
</reciever>
your manifest call is correct, what about your receiver?
according Reto Meier in his legendary Deep Dive Into Location, you should use:
<receiver android:name=".receivers.PowerStateChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
<action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
</intent-filter>
</receiver>
and your receiver activity should check
boolean batteryLow = intent.getAction().equals(Intent.ACTION_BATTERY_LOW);
i took it one step beyond and listen to 5 battery related events:
<receiver android:name=".ReceiverBatteryLevel">
<intent-filter>
<action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
<action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="android.intent.action.ACTION_BATTERY_CHANGED"/>
</intent-filter>
</receiver>
and then receive them like this (abbreviated, fill in the end)
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
public class ReceiverBatteryLevel extends BroadcastReceiver {
private final String TAG = "TGbattery";
int scale = -1;
int level = -1;
int voltage = -1;
int temp = -1;
public void onReceive(Context context, Intent intent) {
Log.d(TAG,"battery Receiver was called now");
String deviceUuid = "INVALID_IMEI";
boolean batteryLow = intent.getAction().equals(Intent.ACTION_BATTERY_LOW);
boolean batteryOK = intent.getAction().equals(Intent.ACTION_BATTERY_OKAY);
boolean batteryPowerOn = intent.getAction().equals(Intent.ACTION_POWER_CONNECTED);
boolean batteryPowerOff = intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED);
boolean batteryChange = intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED);
String intentAction = intent.getAction();
// register SHUTDOWN event
try {
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
temp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
Log.d(TAG,intentAction+" batteryChange="+batteryChange+" flagLo="+batteryLow+" batteryOK="+batteryOK+" batteryPowerOn="+batteryPowerOn+" batteryPowerOff="+batteryPowerOff+"\n level="+level+" temp="+temp+" scale="+scale+" voltage="+voltage);
} // catch etc
}
}
must confess that i dont like the BatteryManager results. any criticism is welcome.