Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to show markers all the time by AsyncTask or Handler in google map version 2

The final thing I am doing is: I have the google map in my application with som buttons and extra stuffs. but I also have to show the updated location of a marker all the time inside my map (I will get the data from external device not gps sensor of android phone). So I thought using thread first but then changes to AsyncTask as you see in my code and tried to use addMarker method there but every time I run it map just stopps working. I want to just show one marker on map now but now successful! The GoogleMap map cannot be reachable via UI thread and inside AsyncTask why? anybody encountered this? what should i do to solve this... plz help

 package com.example.mapsversion2;

    //All imports

    public class MainActivity extends Activity  {
    static final LatLng exmpoint = new LatLng(59.331438,18.064957);

    public static GoogleMap map;

    Button button;
    Button waypointButton;
    Button destinationButton;
    Marker wayPoint;
    TextView positiontext;
    int countclick= 3;
    public static DataModel autoboxdata= new DataModel();
    public static Bitmap arrowBitmap;
    Marker currentPlace;
    MapFragment mapF;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
     mapF = ((MapFragment) getFragmentManager().findFragmentById(R.id.map));
     map= mapF.getMap();
     map.setMapType(GoogleMap.MAP_TYPE_HYBRID);

    //  positiontext = (TextView) findViewById(R.id.position);

    // Move the camera instantly to hamburg with a zoom of 15.
    map.moveCamera(CameraUpdateFactory.newLatLngZoom(exmpoint,15));

    // Zoom in, animating the camera.
    map.animateCamera(CameraUpdateFactory.zoomTo(6), 2000, null);

    addListenerOnButton();
    map.setOnMarkerDragListener(this);

    new PositionUpdate1().execute(); 
  }
    @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
  }

  public void addListenerOnButton() {

        destinationButton= (Button) findViewById(R.id.destinationB);

        destinationButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                //do something
            }
        });     
    }

  }

    public class PositionUpdate1  extends AsyncTask<Void, Void, Void>{


    @Override
    protected Void doInBackground(Void...arg0) {
        // TODO Auto-generated method stub


        map.addMarker(new MarkerOptions()
            .position(hereIam) );

        System.out.println("hej");
        return null;
    } 
  }
    } 

Here is the LogCat:

02-17 18:57:17.805: E/AndroidRuntime(9905): FATAL EXCEPTION: main
02-17 18:57:17.805: E/AndroidRuntime(9905): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.mapsv2/com.example.mapsv2.MainActivity}: java.lang.NullPointerException
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread.access$600(ActivityThread.java:140)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.os.Looper.loop(Looper.java:137)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread.main(ActivityThread.java:4898)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at java.lang.reflect.Method.invokeNative(Native Method)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at java.lang.reflect.Method.invoke(Method.java:511)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at dalvik.system.NativeStart.main(Native Method)
02-17 18:57:17.805: E/AndroidRuntime(9905): Caused by: java.lang.NullPointerException
02-17 18:57:17.805: E/AndroidRuntime(9905):     at com.example.mapsv2.MainActivity.onCreate(MainActivity.java:140)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.Activity.performCreate(Activity.java:5206)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1083)
02-17 18:57:17.805: E/AndroidRuntime(9905):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
02-17 18:57:17.805: E/AndroidRuntime(9905):     ... 11 more
02-17 18:57:17.935: E/android.os.Debug(2287): !@Dumpstate > dumpstate -k -t -z -d -o /data/log/dumpstate_app_error
like image 327
Vivere_FlowCoder Avatar asked Feb 16 '13 08:02

Vivere_FlowCoder


2 Answers

You are trying to add a marker to the map in the background thread, but you can't update UI in Android from thread other than UI thread. So, move your map.addMarker call to the onPostExecute method, which is called in UI thread after background operation is complete:

public class PositionUpdate1  extends AsyncTask<Void, Void, Location> {

    @Override
    protected Location doInBackground(Void...arg0) {
        // get your location...
        return hereIam;
    }

    @Override
    protected void onPostExecute(Location loc) {
        map.addMarker(new MarkerOptions().position(loc));
    }
}

If you want to update the marker continuously, the easiest way is to use a Handler:

public class MainActivity extends Activity {

    final int MARKER_UPDATE_INTERVAL = 2000; /* milliseconds */
    Handler handler = new Handler();

    GoogleMap map;
    Marker marker;
    Location location;

    Runnable updateMarker = new Runnable() {
        @Override
        public void run() {
            marker.remove();
            marker = map.addMarker(new MarkerOptions().position(location));

            handler.postDelayed(this, MARKER_UPDATE_INTERVAL);
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        map = ...; // get map
        location = ...; // get location
        marker = map.addMarker(new MarkerOptions().position(location));

        handler.postDelayed(updateMarker, MARKER_UPDATE_INTERVAL);
    }

    @Override
    protected void onDestroy() {
        handler.removeCallbacks(updateMarker);

        super.onDestroy();
    }
}
like image 129
whyleee Avatar answered Nov 01 '22 00:11

whyleee


You can do something like this. Load the data you need in doInBackground and draw the markers in onProgressUpdate. To call onProgressUpdate just do a publishProgress() from doInBackground. That way you can update the UI from within the ASyncTask. Works for me.

public class CDrawHotspotsAsync extends AsyncTask<Void, CHotspot, Boolean>
{
private final Context mCntxt;
private final GoogleMap mGMap;

// ---------------------------------------------------------

public CDrawHotspotsAsync(Context cntxt, GoogleMap gmap)
{
    this.mCntxt = cntxt;
    this.mGMap = gmap;
}

// ---------------------------------------------------------

private void drawMarker(GoogleMap gmap, CHotspot hotspot)
{
    // Set marker options
    MarkerOptions mo = new MarkerOptions();
    mo.position(hotspot.getPosition());
    mo.title(hotspot.getName());
    String descr = hotspot.getAddress() + ", " + hotspot.getPostal() + ", " + hotspot.getCity();
    mo.snippet(descr);
    mo.icon(BitmapDescriptorFactory.fromResource(R.drawable.hotspot_marker));

    // Add marker to map
    gmap.addMarker(mo);
}

// ---------------------------------------------------------

@Override
protected Boolean doInBackground(Void... params)
{
    // Get hotspots from database
    CHotspotList hotspots = new CHotspotList(this.mCntxt);
    ArrayList<CHotspot> arrHotspots = hotspots.getHotspotList();

    for (CHotspot hotspot : arrHotspots)
    {
        // Publish progress
        publishProgress(hotspot);
    }

    // Always return true
    return true;
}

// ---------------------------------------------------------

@Override
protected void onProgressUpdate(CHotspot... hotspot)
{
    // Draw the marker
    drawMarker(this.mGMap, hotspot[0]);
}
}
like image 38
marcelhoffs Avatar answered Oct 31 '22 22:10

marcelhoffs