web-dev-qa-db-ja.com

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) 

なぜこうなった?私は何か間違っていますか?

25
Rahul Kulhalli

mapClass.Java内のonEventにはパラメーターがないためだと思います。期待されるパラメーターで試してみてください。

16
elsennov

ビルドにproguardを使用している場合、これらの行がproguard構成ファイルにあることを確認してください。

-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
105
Lavakush

私は同じ問題に直面し、長い研究の後にすべての場合の解決策を得ました。この問題は、イベントバスをEventBus.getDefault().register(this)として登録しようとしているクラス内に@SubscribeパブリックメソッドonEvent()がないためです。クラスをイベントバスに登録する場合、この関数の存在は必須です。

これには2つの状況があります

  1. progruadの使用:progruadはメソッドonEvent()の名前を変更する場合があります。これは、イベントバスがそれを見つけることができないためです。これらの行をprogruadルールに設定します

    -keepattributes 注釈

    -keepclassmembersクラス** {

    @ org.greenrobot.eventbus.Subscribe;

    }

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

}

  1. progruardを使用していない場合、クラスには@Subscribeアノテーション付きのメソッドonEvent()がありません。メソッドを使用したこのアノテーションは、EventBusバージョン3.0.0では必須であるため、クラス内でこのメソッドの存在を再確認してください。
10
saksham

ProGuard

ProGuardはメソッド名を難読化し、呼び出されないメソッドを削除する場合があります(デッドコードの削除)。 Subscriberメソッドは直接呼び出されないため、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);
}
5

あなたのコードが私のようなものである場合に備えて:p

メソッドは現在publicであるため、privateとして設定する必要がありました。

5
Woppi

私の状況では、EventBusを登録するクラスで@Subscribeを記述しなかったため、このエラーが発生しました。

5
Allen Vork

私の場合、onEvent()privateで、child classに配置されていました。

しかし、register()unregister()親クラスで呼び出されました。

解決策はonEvent()publicにすることでした。

3
Johnny Five

それが誰かを助けてくれることを念頭に置いて、私の場合、受信メソッドに引数を渡すのを忘れましたが、他のすべては大丈夫でした。受信側の関数/メソッドに引数が渡されない場合、この場合、この例外がスローされます。

2
Wajid Ali

補足として、EventBusの Googleの実装 からこれに切り替えた後、同じエラーが発生しました。 GoogleのEventBusにも@Subscribeアノテーションがあり、greenrobotが提供するアノテーションの代わりにそれを使用していたため、このエラーに夢中になりました。

enter image description here

OK、それは私の側では非常にばかげたエラーですが、私のような1人でも助けることができれば、私は幸せです。

2
rTECH

Proguardを使用している場合、デバッグモードでこの問題に直面することはありません。リリースバージョンでこの問題に直面しました。 proguard-rules.proファイルに以下のコードを追加すると、問題が解決しました。

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