I have a service that listens to location changes and sends message to UI thread together with Polylineoptions, it goes like this:
//some code here
Bundle bundle = new Bundle();
bundle.putParcelable("polylineOptions", mPolylineOptions);
Message msg = Message.obtain(null, LOCATION_UPDATE);
msg.setData(bundle);
mMainHandler.dispatchMessage(msg);
//some more code
mPolylineOptions contains new location together with all previous locations. in the main thread i have handleMessage method that should update my map. it gos like this:
private class MainHandler extends Handler {
private MainHandler (Looper looper){
super(looper);
}
@Override
public void handleMessage (Message msg){
switch (msg.what){
case TrackingService.LOCATION_UPDATE:
if (D){Log.d(TAG, "Location update received");};
myPolylineOptions = (PolylineOptions) msg.getData().getParcelable("polylineOptions");
new Color();
myPolyline = mMap.addPolyline(myPolylineOptions
.color(Color.argb(128, 255, 0, 0))
.geodesic(true));
break;
}
}
}
i can see that handler receives the message, but I get "illegalstateexception: Not On The Main Thread" when i call
myPolyline = mMap.addPolyline(myPolylineOptions
.color(Color.argb(128, 255, 0, 0))
.geodesic(true));
Anybody has ideas how to solve this? Thanks!
EDIT:
I bound to service and pass to it my UI Handler like this:
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
if (D) {Log.d(TAG, "main - onServiceConnected started");};
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
while (mService.getThreadHandler() == null){
try {
Thread.sleep(100);
if(D) {Log.d(TAG, "Thread Handler is not ready");};
} catch (Exception e){}
}
mThreadHandler = mService.getThreadHandler();
mService.setHandler(new MainHandler(Looper.getMainLooper()));
}
Code for a thread. this thread runs in a service:
I know, this thread class is very "dirty" inelegant and unprofessional....
private class ThreadHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MAIN_HANDLER:
if(D) {Log.d(TAG, "main hadler received");};
break;
}
super.handleMessage(msg);
}
}
public LocationThread (Context context){
mContext = context;
keepOn = true;
}
public void cancel() {
keepOn = false;
if (D){Log.d(TAG, "thread was canceled");};
}
public void run(){
try {
Looper.prepare();
} catch (Exception e) {}
// create handler for communication
mThreadHandler = new ThreadHandler();
// setup location updates
Location mLocation;
Location lastLocation = null;
PolylineOptions mPolylineOptions = new PolylineOptions();
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // Use high accuracy
mLocationRequest.setInterval(UPDATE_INTERVAL); // Set the update interval to 5 seconds
mLocationRequest.setFastestInterval(FASTEST_INTERVAL); // Set the fastest update interval to 1 second
mLocationClient = new LocationClient(mContext, this, this);
mLocationClient.connect();
while (keepOn){
try {
Thread.sleep(10000);
} catch (Exception e){}
if (mConnected){
if (D) {Log.d(TAG, "thread is running");};
mLocation = mLocationClient.getLastLocation();
if (lastLocation == null) {
LatLng mLatLng = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
mPolylineOptions.add(mLatLng);
lastLocation = mLocation;
}
// Report to the UI that the location was updated
float distance = mLocation.distanceTo(lastLocation);
if (distance > 1){
LatLng mLatLng = new LatLng(mLocation.getLatitude(), mLocation.getLongitude());
mPolylineOptions.add(mLatLng);
new Color();
lastLocation = mLocation;
}
if (hasBindedActivity){
Bundle bundle = new Bundle();
bundle.putParcelable("polylineOptions", mPolylineOptions);
Message msg = Message.obtain(null, LOCATION_UPDATE);
msg.setData(bundle);
mMainHandler.dispatchMessage(msg);
}
}
}
Looper.loop();
}