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
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();
}
}
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]);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With