I am trying to update markers on Google map using a service, but when I use the "setParkingSpotMarker" function that add a marker to every item at the list I get an error "java.lang.IllegalStateException: Not on the main thread"
The function "setParkingSpotMarker" is called in the loop inside the service -DataUpdateService.
I don't know how to change my code so it will update the markers on the main thread.I have read some posts about that but didn't understand how to change it in my code.
this is the service:
package com.example.sailon;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
public class DataUpdateService extends Service {
Timer myTimer = new Timer();
MyTimerTask myTask = new MyTimerTask();
MyMap mymap;
String teamID;
static LatLng teamLocation;
ArrayList<TeamsList> teamsList= new ArrayList<TeamsList>() ;
public ArrayList<UnitInHeatForMap> unitswithteam= new ArrayList<UnitInHeatForMap>();
String action;
Context fromContext;
String CompName;
String heatNum;
boolean isSailor;
String usermail;
GPSTracker gps;
private final IBinder mBinder = new LocalBinder();
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("PS", "DataUpdateService onStartCommand");
return Service.START_NOT_STICKY;
}
@Override
// return thee instance of the local binder to the activity
public IBinder onBind(Intent intent) {
Log.d("PS", "DataUpdateService onBind");
return mBinder;
}
public class LocalBinder extends Binder {
DataUpdateService getService() {
Log.d("PS", "DataUpdateService LocalBinder onBind");
return DataUpdateService.this;
}
}
public class MyTimerTask extends TimerTask {
@Override
public void run() {
String unitToUpdate= mymap.getUnitToUpdate (CompName,heatNum,usermail);
Log.d("NY","CompName " +CompName);
Log.d("NY","heatNum " +heatNum);
Log.d("NY","usermail " +usermail);
Log.d("NY","unitToUpdate" +unitToUpdate);
Log.d("NY","isSailor" +isSailor);
if (isSailor){
gps = new GPSTracker(DataUpdateService.this,unitToUpdate );
if( ! (gps.canGetLocation())){
gps.showSettingsAlert();
}
}
unitswithteam=mymap.refresh (CompName,heatNum);
int j= unitswithteam.size();
for (int i=0; i<j;i++){
teamID=unitswithteam.get(i).getTeamID();
Log.d("NY","teamID "+i+teamID);
UnitsInHeats us=unitswithteam.get(i).getUnit();
teamLocation = new LatLng(us.getLat(),us.getLng() );
Log.d("NY","team location "+i + " "+us.getLat());
mymap.setParkingSpotMarker(teamLocation,teamID);
if (i==(j-1)){
CameraPosition secound =new CameraPosition.Builder()
.target(teamLocation)
.zoom(15.5f)
.bearing(300)
.tilt(50)
.build();
mymap.moveMyMapCamera(secound);
}
}
}
}
// called from the activity
public void MapUpdateFromService(Context context, MyMap map, final String action,
String CompName, String heatNum, boolean isSailor , String usermail) {
Log.d("PS", "DataUpdateService MapUpdateFromService");
this.mymap = map;
this.action = action;
this.CompName=CompName;
this.heatNum=heatNum;
this.isSailor=isSailor;
this.usermail=usermail;
// this command activate the run function from the inner class MyTimerTask every 5 seconds.
myTimer.schedule(myTask,0,5000);
}
public void onDestroy() {
super.onDestroy();
// cancel the scheduler.
myTimer.cancel();
}
}
this is the activity that calls the service:
package com.example.sailon;
import java.util.ArrayList;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
public class Map extends Activity {
Bundle extras;
// private GoogleMap map;
static LatLng teamLocation;
//public static ArrayList<Teams> teams;
ArrayList<TeamsList> teamsList= new ArrayList<TeamsList>() ;
Marker mark;
double lat;
double lng;
GPSTracker gps;
String Location ;
String teamID;
String CompName;
MyMap mymap;
String heatNum;
String CompID;
boolean isSailor;
String usermail;
static LatLng BeerSheva = new LatLng(31.250919, 34.783916);
public ArrayList<UnitInHeatForMap> unitswithteam= new ArrayList<UnitInHeatForMap>();
// ArrayList<LatLng> List= new ArrayList<LatLng>() ;
DataUpdateService dbuService;
boolean dbuBound=false;// when service connected get true
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
mymap= new MyMap(this,((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap());
//map=((MapFragment)getFragmentManager().findFragmentById(R.id.map)).getMap();
extras = getIntent().getExtras();
CompName=extras.getString("CompName");
heatNum=extras.getString("heatNum");
isSailor=extras.getBoolean("isSailor");
usermail=extras.getString("usermail");
Log.d("CompName",CompName);
Log.d("heatNum",heatNum);
// get action bar
ActionBar actionBar = getActionBar();
// Enabling Up / Back navigation
actionBar.setDisplayHomeAsUpEnabled(true);
if (mymap!=null){
Log.d("PS", "map isnt null");
mymap.setMapType();
mymap.setMyLocationEnabled(true);
CameraPosition firstZom =new CameraPosition.Builder()
.target(BeerSheva)
.zoom(15.5f)
.bearing(300)
.tilt(50)
.build();
mymap.moveMyMapCamera(firstZom);
}
}
// serviceConnerction is an interface that must be implemented when using bound service
private ServiceConnection sConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("PS", "Map onServiceConnected");
DataUpdateService.LocalBinder binder=(DataUpdateService.LocalBinder)service;
dbuService=binder.getService();
Log.d("PS", "Map callupdate");
dbuService.MapUpdateFromService(Map.this,mymap,"ActionSearch",CompName,heatNum, isSailor,usermail);
dbuBound=true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d("PS", "Map onServiceDisconnected");
dbuBound=false;
}
};
@Override
protected void onStart() {
super.onStart();
// Bind to DataUpdateService
Log.d("PS", "Map onStart");
Intent intent= new Intent(this,DataUpdateService.class);
bindService(intent,sConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
Log.d("PS", "Map onStop");
if(dbuBound){
unbindService(sConnection);
dbuBound=false;
}
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main_actions, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Take appropriate action for each action item click
switch (item.getItemId()) {
case R.id.logoutAction:
Intent i = new Intent(Map.this, MainActivity.class);
startActivity(i);
return true;
case R.id.VideoAction:
Intent intent = new Intent("android.media.action.VIDEO_CAMERA");
startActivity(intent);
return true;
case R.id.CallAction:
Intent call = new Intent(Intent.ACTION_DIAL);
startActivity(call);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
this is the calss of the map: package com.example.sailon;
import android.content.Context;
import android.util.Log;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.parse.ParseException;
import java.util.ArrayList;
/**
* Created by Evyatar.m on 21/02/2015.
*/
public class MyMap {
private GoogleMap map;
static LatLng BeerSheva = new LatLng(31.250919, 34.783916);
String CompID;
String teamID;
String CompName;
String heatNum;
ArrayList<TeamsList> teamsList= new ArrayList<TeamsList>() ;
public ArrayList<UnitInHeatForMap> unitswithteam2= new ArrayList<UnitInHeatForMap>();
static LatLng teamLocation;
Model DB;
public MyMap(Context context, GoogleMap map) {
Log.d("PS", "MyMap builder");
DB = Model.getInstance(context);
this.map = map;
}
public String getUnitToUpdate (String CompName,String heatNum, String usermail){
String unit=null;
try {
CompID= DB.getCompIDByName(CompName);
} catch (com.parse.ParseException e) {
e.printStackTrace();
}
try {
unit= DB.getUnitToUpdateFromDB (CompID,heatNum, usermail);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return unit;
}
public void setMyLocationEnabled(boolean b){
Log.d("PS", "MyMap set location enable");
map.setMyLocationEnabled(true);
}
public void setParkingSpotMarker(LatLng teamLocation,String teamID) {
Log.d("PS", "ParkingMap setParkinSpotMarker");
map.addMarker(new MarkerOptions()
.position(teamLocation)
.icon(BitmapDescriptorFactory.fromResource(R.drawable.iconsmall))
.title("Team " +teamID)).showInfoWindow();
}
public void setMapType(){
Log.d("PS", "MyMap setType");
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
public void moveMyMapCamera(CameraPosition firstZom) {
Log.d("PS", "MyMap moveParkingMapCamera");
map.moveCamera(CameraUpdateFactory.newCameraPosition(firstZom));
}
//updates all points on map
public ArrayList<UnitInHeatForMap> refresh (String CompName,String heatNum){
Log.d("PS", "MyMap refresh");
try {
CompID= DB.getCompIDByName(CompName);
} catch (com.parse.ParseException e) {
e.printStackTrace();
}
try {
DB.setUnitInHeatForMap (new Model.CallbackModel () {
@Override
public void done (ArrayList<UnitInHeatForMap> unitswithteam){
if (unitswithteam.size() >0){
unitswithteam2=unitswithteam;
}
}
}, CompID, heatNum,this);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return unitswithteam2;
}
}
please help me thanks !!!**