ACTION_BATTERY_LOW not being fired from manifest?

2019-02-15 14:11发布

问题:

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?

回答1:

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.



回答2:

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)



回答3:

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.



回答4:

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>


回答5:

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.