I want to get the battery status of an Android device at regular intervals.

As it is a bad idea to poll for battery changes every couple of minutes, I wanted to use a repeating alarm, which goes off maybe once an hour, to call a class which gets the current battery status.

However my current implementation is giving me an exception:

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

The class which is called when the alarm times out is as follows:

public class GetBatteryStatusTimeout extends BroadcastReceiver{
    private static final String TAG = "GetBatteryStatusTimeout";
    @Override
    public void onReceive(Context context, Intent intent) {
        BatteryDataManager batteryData = new BatteryDataManager(context);
        batteryData.getStatus();
        Log.e(TAG, "GetBatteryStatus timer expired, getting status");
    }
}

The getStatus() method calls the code to register for the sticky intent and get the battery status:

IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING;
boolean fullyCharged = status == BatteryManager.BATTERY_STATUS_FULL;
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);

It is the point at which I register for this receiver that the exception is thrown.

I understand what the exception is saying (I think!) but I am not calling the code to register for the sticky intent from within another receiver?

The alarm receiver calls another class which then registers the receiver for the battery changed intents.... but obviously this isn't allowed either?

What is the alternative?

Also the exception is only thrown on some devices, and the app works fine on others?

有帮助吗?

解决方案

This is actually an Android bug. You aren't actually trying to register a BroadcastReceiver for an asynchronous callback in this case, but Android throws this exception anyway.

To get around this, instead of calling

context.registerReceiver(null, ifilter);

to get the sticky broadcast, do this:

context.getApplicationContext().registerReceiver(null, ifilter);

The application Context has a longer lifetime than the receiver's Context, so the call will be allowed.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top