Search code examples
javaandroidbroadcastreceiverintentfilter

Local Broadcast Receiver Exception: android.app.IntentReceiverLeaked?


NOTE: Activity Flag with android:excludeFromRecents="true"

@Override
    protected void onDestroy() {

        sendBroadcast(new Intent("com.android.servicerestart"));
        if(broadcastReceiver != null) {
            try {
                unregisterReceiver(broadcastReceiver);
            }
            catch (IllegalArgumentException E)
            {

            }
        }

        super.onDestroy();
        Log.e("Activity","In OnDestroy");
    }

    @Override
    protected void onPause() {

        if(broadcastReceiver != null) {
            try {
                unregisterReceiver(broadcastReceiver);
            }
            catch (IllegalArgumentException E)
            {
                E.printStackTrace();
            }
        }
        super.onPause();
        Log.e("Activity","In OnPause");
    }

    @Override
    protected void onResume() {

        registerReceiver();
        super.onResume();
        Log.e("Activity","In onResume");
    }

    @Override
    protected void onStart() {
        super.onStart();
        try {
            registerReceiver();
        }
        catch (Exception E)
        {

        }
    }

registerReceiver();

private void registerReceiver() {
    broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

        }
    };

    try {
        registerReceiver(broadcastReceiver, new IntentFilter("*******.receive.service.download"));
    }
    catch (Exception E)
    {

    }
}

Logs

E/ActivityThread: Activity **********.activity.MainActivity has leaked IntentReceiver **********.activity.MainActivity$3@3318724 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity **********.activity.MainActivity has leaked IntentReceiver **********.activity.MainActivity$3@3318724 that was originally registered here. Are you missing a call to unregisterReceiver()?
    at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1164)
    at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:951)
    at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1308)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1288)
    at android.app.ContextImpl.registerReceiver(ContextImpl.java:1282)
    at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:586)
    at **********.activity.MainActivity.registerReceiver(MainActivity.java:203)
    at **********.activity.MainActivity.onStart(MainActivity.java:156)
    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1255)
    at android.app.Activity.performStart(Activity.java:6853)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2712)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2810)
    at android.app.ActivityThread.-wrap12(ActivityThread.java)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1530)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6256)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:793)

Solution

  • This is a Lifecycle issue

    Both start and resume register a receiver - but there is no check whether a receiver already exists (so you register two separate receivers)

    This means on pause and destroy methods can only see the second one and the first is leaked.

    The best fix is to remove the start/destroy blocks. Otherwise you may wrap your new BroadcastReceiver block in if (broadcastReceiver == null)