3

I am trying to delete the markers from the Goolge map in the FragmentActivity Map when there is no data available in the table for the makers on the serverside also the data object is empty but I am getting the error below. How can I fix it?

Error:

07-12 20:53:05.697: E/AndroidRuntime(26364): FATAL EXCEPTION: IntentService[IntentService]
07-12 20:53:05.697: E/AndroidRuntime(26364): Process: com.bustracker, PID: 26364
07-12 20:53:05.697: E/AndroidRuntime(26364): java.lang.IllegalStateException: Not on the main thread
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.l.a.ce.b(Unknown Source)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.maps.api.android.lib6.d.ct.a(Unknown Source)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.maps.api.android.lib6.d.aq.a(Unknown Source)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.android.gms.maps.model.internal.t.onTransact(SourceFile:51)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at android.os.Binder.transact(Binder.java:380)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.android.gms.maps.model.internal.zzi$zza$zza.remove(Unknown Source)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.google.android.gms.maps.model.Marker.remove(Unknown Source)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at com.bustracker.GetLLRD.onHandleIntent(GetLLRD.java:120)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at android.os.Handler.dispatchMessage(Handler.java:102)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at android.os.Looper.loop(Looper.java:145)
07-12 20:53:05.697: E/AndroidRuntime(26364):    at android.os.HandlerThread.run(HandlerThread.java:61)

onHandleIntent method in the GetLLRD IntentService class:

protected void onHandleIntent(Intent intent) {

                            if (data != null && !data.isEmpty()) {
                                Intent intent1 = new Intent(this, Map.class);
                                intent1.putExtra("list_data", data);
                                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                        | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                                startActivity(intent1);

                            } else if (Map.markerMap != null
                                    && !Map.markerMap.isEmpty()) {

                                Iterator<HashMap.Entry<Integer, Marker>> it = Map.markerMap
                                        .entrySet().iterator();
                                while (it.hasNext()) {
                                    HashMap.Entry<Integer, Marker> entery = it
                                            .next();
                                    int key = entery.getKey();
                                    Map.marker = Map.markerMap.get(key);
                                    System.out.println("test marker " + Map.marker ); 
                                    //Line 120.
                                    Map.marker .remove();
                                    Map.markerMap.remove(key);

                                    // Marker value = entery.getValue();
                                }
                            }

Map fragmentActivity:

public class Map extends FragmentActivity implements OnMapReadyCallback {

    GoogleMap map;
    static HashMap<Integer, Marker> markerMap = new HashMap<Integer, Marker>();
    static Marker marker = null;

    ...
    }
The Time
  • 697
  • 5
  • 12
  • 26
  • `onHandleIntent()` runs on a worker thread. GoogleMap updates can only be made from the main thread. Is there a reason you are using an `IntentService` to update the map instead of in your activity? – Bob Snyder Jul 12 '15 at 21:45
  • @ qbix : I have checkboslist where the user can selects some routes in the MainActivity then the alaramManger starts firing, in the IntentService a request is being sent to the server to get the data afterwards I have to start the Map FragmentActivity to pass the data to it or to update it. Therefore I am using IntentService. – The Time Jul 12 '15 at 23:13

2 Answers2

8

A quick fix for the exception would be to put the map updates in a Runnable to execute on the main thread (code below). However, the real answer to the question is that you need to re-think your design. It is unsafe for code in an IntentService to be using static data in an activity. What are the reasons for using an IntentService? The map updates must run on the main thread. One of the purposes of an IntentService is to perform operations that cannot be done on the main thread, and need a background thread. Why use an IntentService when it contains has code that needs the main thread?

    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            Iterator<HashMap.Entry<Integer, Marker>> it = Map.markerMap
                    .entrySet().iterator();
            while (it.hasNext()) {
                HashMap.Entry<Integer, Marker> entery = it
                        .next();
                int key = entery.getKey();
                Map.marker = Map.markerMap.get(key);
                System.out.println("test marker " + Map.marker );
                //Line 120.
                Map.marker.remove();
                // Remove from map using iterator
                it.remove();

                // Marker value = entery.getValue();
            }
        }
    });
Bob Snyder
  • 37,759
  • 6
  • 111
  • 158
  • I have checkboslist where the user can selects some routes in the MainActivity then the alaramManger starts firing, in the IntentService a request is being sent to the server to get the data afterwards I have to start the Map FragmentActivity to pass the data to it or to update it. Therefore I am using IntentService. I have tried your answer code but I am getting `java.util.ConcurrentModificationException` – The Time Jul 12 '15 at 23:14
  • The exception is caused by removing an entry from markerMap while you are iterating over it. [Related issue](http://stackoverflow.com/questions/17693652/concurrentmodificationexception-while-iterating-map). I'll edit my answer. – Bob Snyder Jul 12 '15 at 23:45
  • I editted my answer to use [Iterator.remove()](http://developer.android.com/reference/java/util/Iterator.html#remove()) to remove the marker from the map. – Bob Snyder Jul 13 '15 at 04:25
  • Saved my life in jetpck compose :) – InsaneCat Apr 12 '22 at 16:21
0

You cannot start activity from background thread. Code in onHandleIntent is executed in background thread. To start activity from main thread you need to post a runnable to main threads looper.

protected void onHandleIntent(Intent intent) {

      if (data != null && !data.isEmpty()) {

         Handler mainHandler = new Handler(getApplicationContext.getMainLooper());
         mainHandler.post(new Runnable() {
                          @Override
                          public void run() {
                                 Intent intent1 = new Intent(this, Map.class);
                                 intent1.putExtra("list_data", data);
                                 intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                    | Intent.FLAG_ACTIVITY_SINGLE_TOP);

                                 startActivity(intent1);}
                              });        

      } else if (Map.markerMap != null && !Map.markerMap.isEmpty()) {..........}
}
callOfCode
  • 893
  • 8
  • 11