I'm currently developing an Android app that have to receive GPS positions from other devices every minutes, and display them on a map. I'm using the GoogleMaps Api V2,
What i'd like to do, is to refresh the position marker very time a new position is received. (I don't want to refresh the whole map)
For the moment, I've added a button in the menu that enables me to refresh the entire map.
To detail to structure, I have a service that run MQTT, and every time a position is received, I add it into an Hashmap, that represents my map data source. This HashMap is a Singleton that extends Observable. Moreover, my fragment that display the my implements Observer.
Code from my Fragment that implements Observer
public void update(Observable observable, final Object object)
{
if (observable instanceof ListPositions && object != null)
{
Position p = (Position) object;
LatLng position = new LatLng(p.getLatitude(), p.getLongitude());
// Where i'd like to move the markers
}
else
{
// Where i'd like to remove the marker from the map
}
}
Code From my Singleton List of position
public class ListPositions extends Observable{
private HashMap<String,Position> mapPosition;
private ListPositions()
{
mapPosition = new HashMap<String, Position>();
VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
this.addObserver(mapFragmentObserver);
}
private static ListPositions INSTANCE = null;
public static synchronized ListPositions getInstance()
{
if (INSTANCE == null)
{ INSTANCE = new ListPositions();
}
return INSTANCE;
}
public int getNumberOfPosition()
{
return mapPosition.size();
}
public void addPosition(String key, Position p){
mapPosition.put(key,p);
setChanged();
notifyObservers(p);
}
public void removePosition(String key){
mapPosition.remove(key);
setChanged();
notifyObservers();
}
Code From myService that runs MQTT
public void onPositionMessageReceived(MqttMessage message, String source)
{
Gson gson = new Gson();
String s = gson.toJson(message.toString());
String jsonPosition = gson.toJson(message.toString());
jsonPosition = formatMessage(jsonPosition);
Position p = gson.fromJson(jsonPosition, Position.class);
ListPositions.getInstance().addPosition(source, p);
}
Can someone know how to move each markers individually without refreshing the whole map, in my update function from my Observer Fragment? May I use a Handler to update the Map, from an other thread to modify the Main UI Thread ?
Many thanks
EDIT :
Because the first methode given by AniV didn't work for me, I've tried with an Asyntask that runs when my Observer get a notification from the Observable List.
Code from the Observer Fragment :
public void update(Observable observable, final Object object)
{
if (observable instanceof ListPositions && object != null)
{
Position p = (Position) object;
position = new LatLng(p.getLatitude(), p.getLongitude());
options = new MarkerOptions().position(position).title("TEST").snippet("TEST");
PositionUpdate positionUpdaterTask = new PositionUpdate(myGoogleMap, options, position);
positionUpdaterTask.execute();
}
}
Code from the AsyncTask :
public class PositionUpdate extends AsyncTask<Void, Void, Void>{
private GoogleMap myGoogleMap;
private MarkerOptions options;
private LatLng positionToAdd;
public PositionUpdate(GoogleMap googleMap, MarkerOptions options, LatLng position)
{
this.myGoogleMap = googleMap;
this.options = options;
this.positionToAdd = position;
}
@Override
protected Void doInBackground(Void...voids)
{
return null;
}
@Override
protected void onPostExecute(Void aVoid)
{
if (myGoogleMap != null)
{
myGoogleMap.addMarker(options.position(positionToAdd));
Log.i(ConstElisa.LOG_ELISA, "MARKER ADDED");
}
else
{
Log.e(ConstElisa.LOG_ELISA, "ERROR ADDING THE MARKER");
}
super.onPostExecute(aVoid);
}
However, in this case, myGoogleMap variable is always null, so the marker is never added to the Google Map.
Does someone have an idea why this variable is null ?
I finally succeeded in doing that thing by using the AsyncTask.
In my EDIT, I said that I had some trouble with the null instance of my Google Maps object. This was caused by my Singleton Observable. Indeed, in the constructor, I used
VehicleMapFragment mapFragmentObserver = new VehicleMapFragment();
this.addObserver(mapFragmentObserver);
This code sample recreated another instance of my Fragment, and that the reason why ii had Null objects.
To correct this problem, I simply used :
ListPositions.getInstance().addObserver(this);
in my Fragment Observer.
So if you want to update a marker position without refreshing the whole map, you can use the Observer/Observable Pattern, and use an Asynctask to update the marker position.