EventBus — класс подписчика и его суперклассы не имеют общедоступных методов с аннотацией @subscribe.

Я создаю приложение для Android, используя EventBus для отправки асинхронных трансляций другим классам, но во время выполнения я получаю ошибку.

MainActivity.java

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.maps.model.LatLng;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;


public class MainActivity extends AppCompatActivity {

    //Globals
    public String uname = null;
    public double lat = 0;
    public double lng = 0;

    //Get GUI handles
    public Button sendButton; //
    public EditText username;
    public Button MapButton; //
    public EditText LatBox;
    public EditText LngBox;


    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        //register EventBus
        EventBus.getDefault().register(this);

        super.onCreate(savedInstanceState);
        //set GUI for MainActivity
        setContentView(R.layout.activity_main);

        //get handlers
        LatBox = (EditText)findViewById(R.id.LatBox);
        LngBox = (EditText)findViewById(R.id.LngBox);

        MapButton = (Button)findViewById(R.id.locationButton);
        //Call the class which will handle finding coordinates
        MapButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent MapIntent = new Intent(getApplicationContext(), MapClass.class);
                startActivityForResult(MapIntent, 0);
            }
        });

        sendButton = (Button)findViewById(R.id.Submit);
        //Set action for Button
        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //Get username from user
                username  = (EditText)findViewById(R.id.UsernameText);
                uname = username.getText().toString();

                //Generate intent to start IntentService
                Intent i = new Intent(getApplicationContext(), Register.class);

                //Put the extra field of username
                i.putExtra("username", uname);
                i.putExtra("latitude", lat);
                i.putExtra("longitude", lng);
                i.putExtra("type", "meetup.be2015.gcm_meetup.MAIN_ACTIVITY");

                //Start the IntentService on a different thread
                startService(i);
            }
        });

    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEvent(LatLng currentPos){

        LatBox.setText(String.valueOf(currentPos.latitude));
        LngBox.setText(String.valueOf(currentPos.longitude));

        lat = currentPos.latitude;
        lng = currentPos.longitude;
    }
}

MapClass.java

import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

public class MapClass extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private GoogleApiClient mGoogleApiClient;
    private GoogleMap mgoogleMap;
    private LatLng latLng;
    private GoogleApiClient client;

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mgoogleMap = googleMap;
        mgoogleMap.setMyLocationEnabled(true);      //Sets location to current position
        buildGoogleApiClient();
        mGoogleApiClient.connect();
    }

    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
    }

    @Override
    public void onConnected(Bundle bundle) {
        Location MLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (MLastLocation != null) {
            latLng = new LatLng(MLastLocation.getLatitude(), MLastLocation.getLongitude());

            //Post the LatLng to MainActivity
            EventBus.getDefault().post(latLng);

            //Send sticky event to Register and MyGcmListenerService
            EventBus.getDefault().postSticky(latLng);

        } else {
            Log.d("onConnected", "Value of LatLng is NULL");
            latLng = new LatLng(0, 0);   //equator
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        //Notify
        Log.d("ConnectionSuspended", "Connection Suspended. Status: " +   i);
        mgoogleMap.clear();
        mGoogleApiClient.disconnect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        //Notify
        Log.d("ConnectionFailed", "Connection Failed. Status: " + connectionResult.toString());
        mgoogleMap.clear();
        mGoogleApiClient.disconnect();
    }

    @Subscribe
    public void onEvent() {
        Log.d("EVENT", "EVENT");
    }

    @Override
    public void onStart() {
        super.onStart();
        if (!EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this);
        }


    @Override
    public void onStop() {
        super.onStop();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }

    }
}

LogCat показывает следующее:

03-08 22:54:56.970 8570-8570/meetup.be2015.gcm_meetup E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{meetup.be2015.gcm_meetup/meetup.be2015.gcm_meetup.MapClass}:
org.greenrobot.eventbus.EventBusException: Subscriber class meetup.be2015.gcm_meetup.MapClass 
and its super classes have no public methods with the @Subscribe annotation
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2118)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2143)
at android.app.ActivityThread.access$700(ActivityThread.java:140)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:174)
at android.app.ActivityThread.main(ActivityThread.java:4952)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794)
at dalvik.system.NativeStart.main(Native Method)
Caused by: org.greenrobot.eventbus.EventBusException: Subscriber class meetup.be2015.gcm_meetup.MapClass 
and its super classes have no public methods with the @Subscribe annotation
at org.greenrobot.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java:67)
at org.greenrobot.eventbus.EventBus.register(EventBus.java:136)
at meetup.be2015.gcm_meetup.MapClass.onStart(MapClass.java:91)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1178)
at android.app.Activity.performStart(Activity.java:5198)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2091)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2143) 
at android.app.ActivityThread.access$700(ActivityThread.java:140) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1237) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:174) 
at android.app.ActivityThread.main(ActivityThread.java:4952) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:511) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) 
at dalvik.system.NativeStart.main(Native Method) 

Почему это происходит? Я делаю что-то неправильно?


person Rahul Kulhalli    schedule 08.03.2016    source источник
comment
При использовании R8 у нас та же проблема   -  person Duna    schedule 29.12.2019


Ответы (14)


я думаю, это потому, что onEvent внутри MapClass.java не имеет параметра. Не могли бы вы попробовать с ожидаемым параметром?

person elsennov    schedule 10.03.2016
comment
Каков ожидаемый параметр? На самом деле я не хочу ничего получать в MapClass.java - person Rahul Kulhalli; 10.03.2016
comment
Если вы не хотите ничего получать в MapClass.java, то зачем подписываетесь (регистрируетесь)? Просто удалите регистрацию и отмените регистрацию, также onEvent. - person elsennov; 10.03.2016
comment
Я просто хочу отправить LatLng в MainActivity. Я думал, что вам нужно регистрироваться и отменять регистрацию, даже если вы хотите отправлять события с помощью EventBus. Итак, вы говорите, что мне не нужно регистрироваться и отменять регистрацию в EventBus, если я не собираюсь ничего получать? Кроме того, обратное. Мне нужно будет регистрироваться и отменять регистрацию в EventBus только тогда, когда мне нужно получить событие, верно? Что, если мой класс хочет сделать и то, и другое? Извините, если эти вопросы покажутся вам детскими; Я не могу понять концепцию EventBus. Заранее спасибо, @elsennov! :) - person Rahul Kulhalli; 10.03.2016
comment
Да, ты прав. Суть в том, что как подписчик вы должны зарегистрироваться на шине событий, чтобы получить событие, и отменить регистрацию, когда это будет сделано. Но, если вы издатель, вам не нужно регистрироваться - person elsennov; 10.03.2016

Пожалуйста, убедитесь, что эти строки есть в вашем конфигурационном файле proguard, если вы используете proguard для своих сборок.

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
person Lavakush    schedule 08.09.2016
comment
Это спасло мой день - person Jayant Arora; 22.09.2016
comment
легенда, это была моя проблема. - person Donal Rafferty; 19.10.2016
comment
У меня такая же проблема, сделал мой день Спасибо - person MBH; 08.12.2016
comment
Это ответ, если проблема возникает после производства - person tabebqena; 19.02.2020
comment
Двойной ** после класса во второй строке показывает синтаксическую ошибку в последних версиях инструментов. Синтаксис изменился? Что вообще означает двойной **? - person Abhijit; 30.10.2020
comment
выше правила proguard не работали для меня. Доступны ли какие-либо дополнительные обновления? - person Amartya; 27.05.2021
comment
@Amartya Попробуйте добавить строку ниже. Надеюсь, это поможет. -dontskipnonpubliclibraryclassmembers - person Lavakush; 09.06.2021

Я столкнулся с той же проблемой и после долгих исследований получил решение для каждого случая. Эта проблема связана с отсутствием общедоступного метода @Subscribe onEvent() внутри класса, который вы пытаетесь зарегистрировать на шине событий как EventBus.getDefault().register(this). Наличие этой функции обязательно, если вы регистрируете класс с шиной событий.

Это может быть в двух случаях

  1. использование progruad: progruad может изменить имя метода onEvent(), из-за чего шина событий не может его найти. Поместите эти строки в свои правила progruad

    -keepattributes Аннотация

    -keepclassmembers класс ** {

    @org.greenrobot.eventbus.Подписаться ;

    }

    -keep enum org.greenrobot.eventbus.ThreadMode { *;

}

  1. если вы не используете progruard, то определенно в вашем классе отсутствует метод onEvent() с аннотацией @Subscribe. Эта аннотация с методом является обязательной для EventBus версии 3.0.0, поэтому дважды проверьте наличие этого метода внутри вашего класса.
person saksham    schedule 10.05.2017

На всякий случай ваш код похож на мой: p

Мне пришлось установить метод как public, потому что в настоящее время он private.

person Woppi    schedule 24.06.2017

Прогард

ProGuard запутывает имена методов и может удалять методы, которые не вызываются (удаление мертвого кода). Поскольку методы подписчика не вызываются напрямую, ProGuard предполагает, что они не используются. Поэтому, если вы включаете минификацию ProGuard, вы должны сообщить ProGuard, чтобы он сохранял эти методы подписчика.

Используйте следующие правила в файле конфигурации ProGuard (proguard.cfg), чтобы предотвратить удаление подписчиков:

-keepattributes *Annotation*
-keepclassmembers class * {
   @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
 
# Only required if you usenter code heree AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
    <init>(java.lang.Throwable);
}
person Gevorg Gharibyan    schedule 29.04.2019

В моей ситуации я получил эту ошибку, потому что не написал @Subscribe в классе, где я регистрирую EventBus.

person Allen Vork    schedule 21.10.2016

В моем случае onEvent() был частным и помещен в дочерний класс.

Но register() и unregister() вызывались в родительском классе.

Решение состояло в том, чтобы сделать onEvent() общедоступным.

person Johnny Five    schedule 11.10.2018
comment
То же самое. У меня была функция как private, а затем мне пришлось сделать ее public, и это сработало. - person sud007; 26.02.2019

Если вы используете proguard, вы не столкнетесь с этой проблемой в режиме отладки. Я столкнулся с этой проблемой в релизной версии. после добавления приведенного ниже кода в файлы proguard-rules.pro моя проблема решена.

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
 }
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
person Shaon    schedule 17.08.2019

Кстати, я получил ту же ошибку после переключения с реализации Google EventBus на Вот этот. Эта ошибка сводила меня с ума, потому что в EventBus от Google также есть аннотация @Subscribe, и я использовал ее вместо той, которую предоставил greenrobot.

введите здесь описание изображения

Хорошо, это очень глупая ошибка с моей стороны, но если я смогу помочь хотя бы одному человеку вроде меня, я буду счастлив.

person rTECH    schedule 05.11.2018
comment
Это был мой случай. Спасибо. - person shaby; 26.12.2019

Может кому поможет! Моя ситуация, я забыл добавить строку ниже в buildTypes

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

person Duong.Nguyen    schedule 13.05.2020

На всякий случай это кому-то поможет, в моем случае я забыл передать аргументы в метод приема, все остальное было в порядке. Когда принимающей функции/методу не передается аргумент, в этом случае возникает это исключение.

person Wajid    schedule 13.12.2018

Просто переключитесь с приватного развлечения на публичное, и вы увидите волшебство.

person Brahem Mohamed    schedule 09.12.2020

Обновление из ответа, поскольку proguard больше не используется по умолчанию. Его изменение в R8. Выключите R8, чтобы убедиться. В флаттере это будет:

apk сборки флаттера --no-shrink ...

person nafsaka    schedule 06.11.2020

Я использовал аннотацию подписки из неправильного пакета.

Должно быть import org.greenrobot.eventbus.Subscribe

Я использовал import com.squareup.otto.Subscribe

person shaby    schedule 14.02.2020