GreenRobot EventBusException: Subscriber class already registered to event class

nwhess21 picture nwhess21 · May 9, 2015 · Viewed 14.9k times · Source

I have a MainActivity and a Service in my android app. I have registered both to the EventBus and when I start the service from the main activity manually via a switch everything works fine. However, when I start the service from an AlarmManager alarm I my app crashes with the following stack trace:

05-08 21:21:00.051: E/AndroidRuntime(22362): FATAL EXCEPTION: main
05-08 21:21:00.051: E/AndroidRuntime(22362): Process: com.hesselapplications.shade, PID: 22362
05-08 21:21:00.051: E/AndroidRuntime(22362): java.lang.RuntimeException: Unable to start service com.hesselapplications.shade.ShadeService@39251d8 with Intent { cmp=com.hesselapplications.shade/.ShadeService }: de.greenrobot.event.EventBusException: Subscriber class com.hesselapplications.shade.ShadeService already registered to event class com.hesselapplications.shade.EventBus.ColorChangedEvent
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2881)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.app.ActivityThread.access$2100(ActivityThread.java:144)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.os.Handler.dispatchMessage(Handler.java:102)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.os.Looper.loop(Looper.java:135)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.app.ActivityThread.main(ActivityThread.java:5221)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at java.lang.reflect.Method.invoke(Native Method)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at java.lang.reflect.Method.invoke(Method.java:372)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
05-08 21:21:00.051: E/AndroidRuntime(22362): Caused by: de.greenrobot.event.EventBusException: Subscriber class com.hesselapplications.shade.ShadeService already registered to event class com.hesselapplications.shade.EventBus.ColorChangedEvent
05-08 21:21:00.051: E/AndroidRuntime(22362):    at de.greenrobot.event.EventBus.subscribe(EventBus.java:179)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at de.greenrobot.event.EventBus.register(EventBus.java:165)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at de.greenrobot.event.EventBus.register(EventBus.java:133)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at com.hesselapplications.shade.ShadeService.onStartCommand(ShadeService.java:51)
05-08 21:21:00.051: E/AndroidRuntime(22362):    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2864)
05-08 21:21:00.051: E/AndroidRuntime(22362):    ... 9 more

Here is my MainActivty code:

public class MainActivity {

    private SwitchCompat mSwitch;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSwitch = (SwitchCompat) findViewById(R.id.switch_filter);
        mSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) Shade.startShade(MainActivity.this);
                else Shade.stopShade(MainActivity.this);
            }
        });
    }

    public void onEventMainThread(ShadeStartEvent event) {
        mSwitch.setChecked(true);
    }

    public void onEventMainThread(ShadeStopEvent event){
        mSwitch.setChecked(false);
    }

    @Override
    protected void onStart() {
        super.onStart();
        mSwitch.setChecked(Shade.isActive);
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        EventBus.getDefault().unregister(this);
        super.onStop();
    }

}

And here is my Service code:

public class MyService extends Service {

    public void onEvent(ShadeStopEvent event) {
        EventBus.getDefault().unregister(ShadeService.this);
    }

    public void onEvent(ColorChangedEvent event){

    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Shade.stopShade(this);
        super.onTaskRemoved(rootIntent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        EventBus.getDefault().register(ShadeService.this);
        return START_NOT_STICKY;
    }

}

Lastly here is class with the startShade and stopShade methods. This is also the broadcast receiver that receives the aforementioned alarm:

public class Shade extends BroadcastReceiver {

    public static boolean isActive;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (isStartAlarm) {
            startShade(context);
        } else if (isStopAlarm) {
            stopShade(context);
        }
    }

    public static void startShade(Context context) {
        if (!isActive) {
            Intent intent = new Intent(context, ShadeService.class);
            context.startService(intent);
            EventBus.getDefault().post(new ShadeStartEvent());
            isActive = true;
        }
    }

    public static void stopShade(Context context) {
        if (isActive) {
            EventBus.getDefault().post(new ShadeStopEvent());
            Intent intent = new Intent(context, ShadeService.class);
            context.stopService(intent);
            isActive = false;
        }
    }

}

What is causing this crash. How can I resolve it?

Answer

EE66 picture EE66 · May 27, 2015

The issue is the you are trying to register the service twice as you can see in the trace. The service isn't unregistered therefore the easiest option for you is to check whether the service is registered before you register it EventBus.getDefault().isRegistered(...)or check why the service isn't stopped and therefore still registered. For example:

if (!EventBus.getDefault().isRegistered(this)) {
    EventBus.getDefault().register(this);
}