I am getting the following error on Android versions 4.1.2:
Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.example.PluggedInBroadcastReceiver:
android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2287)
at android.app.ActivityThread.access$1600(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4961)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents
at android.app.ReceiverRestrictedContext.registerReceiver(ContextImpl.java:152)
at android.app.ReceiverRestrictedContext.registerReceiver(ContextImpl.java:146)
at com.example.PluggedInBroadcastReceiver.getBatteryLevel(Unknown Source)
at com.example.PluggedInBroadcastReceiver.onReceive(Unknown Source)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2280)
at android.app.ActivityThread.access$1600(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4961)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
at dalvik.system.NativeStart.main(NativeStart.java)
Here is the code that is causing the error. This receiver is being registered statically (in the AndroidManifest.xml) rather than dynamically:
public class PluggedInBroadcastReceiver extends WakefulBroadcastReceiver {
public static final String LOG_TAG = PluggedInBroadcastReceiver.class.getSimpleName();
private IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
String action = intent.getAction();
if (action != null && action.equals(Intent.ACTION_POWER_CONNECTED)) {
try {
Intent batteryStatusIntent = context.getApplicationContext().registerReceiver(null, iFilter);
double battPercentage = BatteryUtils.getBatteryLevel(batteryStatusIntent);
//Do something with the battery percentage value...
} catch (Exception e) {
Log.e(LOG_TAG, "Battery status intent was null");
}
}
}
}
}
I ran into this error in the past and found that my problems were being caused by the fact that the context that is passed to a Broadcast Receiver does not have the ability have registerReceiver() called on it.
I found some resources that suggest that you can convert the context passed to the Broadcast Receiver to an application context and then call registerReceiver() on the application context. This works for Android versions 4.2 and up, but fails on 4.1.2 (and possibly lower, but haven't tested explicitly). It seems like converting to the application context should allow registerReceiver() to be called, but that doesn't seem to work for all versions of Android.
Does anyone have an explanation for this behavior?
EDIT: The plot thickens... I've now learned that this crash has occurred on android versions 4.1.1, 4.1.2, 4.3.0 and 5.1.1 over 93% of the crashes occurred on 4.1.2. I'm not sure we're going to find a solution for this, but my fix going forward is to never call registerReceiver() from a BroadcastReceiver. The behavior seems to be undefined and unpredictable even when using the application context which is apparently supposed to allow this.