Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

illegal state exception when trying to change a marker on a Google Maps v2 Api from a Google Cloud Messaging message

I am writing an android app and I have markers on a Google Map that should be changed to a position that I receive by GCM. I have a global static List in which I save the marker together with an id and the position. I can change the positions of the Objects in the list in my GCMBaseIntentService when I receive a message, but when I want to execute the following code:

    mMarker.setPosition(new LatLng(member.getLatitude(),member.getLongitude()));

I get the following Exception:

    01-13 18:52:38.118: E/AndroidRuntime(7605): FATAL EXCEPTION: IntentService[GCMIntentService-1041237551356-1]
    01-13 18:52:38.118: E/AndroidRuntime(7605): java.lang.IllegalStateException: Not on the main thread
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at maps.am.r.b(Unknown Source)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at maps.ar.d.b(Unknown Source)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at maps.y.ae.addMarker(Unknown Source)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.google.android.gms.maps.internal.IGoogleMapDelegate$Stub.onTransact(IGoogleMapDelegate.java:167)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at android.os.Binder.transact(Binder.java:279)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a.addMarker(Unknown Source)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.example.MapViewActivity.showMember(MapViewActivity.java:529)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.example.MapViewActivity.updateMember(MapViewActivity.java:417)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.example.MapViewActivity.updateMembers(MapViewActivity.java:410)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.example.pushnotifications.GCMIntentService.onMessage(GCMIntentService.java:75)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at com.google.android.gcm.GCMBaseIntentService.onHandleIntent(GCMBaseIntentService.java:223)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:59)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at android.os.Handler.dispatchMessage(Handler.java:99)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at android.os.Looper.loop(Looper.java:130)
    01-13 18:52:38.118: E/AndroidRuntime(7605):     at android.os.HandlerThread.run(HandlerThread.java:60)

I tried adding a button to the map that refreshes all markers (with exactly the same code) and that works fine. So somehow the problem is that the GCM is executed in a different thread or something like that and it seems that I cannot change markers from a different thread...

I tried an ugly solution: To refresh all markers every second. But creating a thread from the MapViewActivity gives the same exception:

private Thread MarkerUpdater = new Thread(
    new Runnable() {
        public void run() {
            while(true) {
                updateMembers();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    });

Maybe someone has an idea how a nice solution could look like?

like image 583
Fabi Avatar asked Jan 13 '13 22:01

Fabi


2 Answers

You need to get the handler for your main UI thread and post a runnable there.

Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable(){ 
   // your UI code here 
}

Any variables you reference from your service in your Runnable will need to be final. Since you said you are sharing the data as global/static, you should be okay.

like image 55
iagreen Avatar answered Sep 18 '22 10:09

iagreen


Try this,

Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
         @Override
         public void run() {
              //your code
         }
});
like image 24
Silambarasan Avatar answered Sep 21 '22 10:09

Silambarasan