Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Android: crash when using library that also uses Lost for location #8639

Closed
chenguo opened this issue Apr 5, 2017 · 6 comments
Closed

Android: crash when using library that also uses Lost for location #8639

chenguo opened this issue Apr 5, 2017 · 6 comments
Assignees
Labels
Android Mapbox Maps SDK for Android release blocker Blocks the next final release

Comments

@chenguo
Copy link

chenguo commented Apr 5, 2017

I'm writing an application that uses MapView. I'm using a library that also uses the Lost API under the hood, and the location updates being requested of that library is crashing MyLocationView:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6902)
    at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1087)
    at android.view.ViewGroup.invalidateChild(ViewGroup.java:5246)
    at android.view.View.invalidateInternal(View.java:13573)
    at android.view.View.invalidate(View.java:13537)
    at android.view.View.invalidate(View.java:13521)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView$MyLocationShowBehavior.invalidate(MyLocationView.java:851)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView.update(MyLocationView.java:379)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView$MarkerCoordinateAnimatorListener.onAnimationUpdate(MyLocationView.java:700)
    at android.animation.ValueAnimator.animateValue(ValueAnimator.java:1346)
    at android.animation.ValueAnimator.end(ValueAnimator.java:1055)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView$MyLocationShowBehavior.updateLatLng(MyLocationView.java:833)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView.setLocation(MyLocationView.java:458)
    at com.mapbox.mapboxsdk.maps.widgets.MyLocationView$GpsLocationListener.onLocationChanged(MyLocationView.java:592)
    at com.mapbox.mapboxsdk.location.LocationSource.onLocationChanged(LocationSource.java:136)
    at com.mapzen.android.lost.internal.LostClientManager.reportLocationChanged(LostClientManager.java:173)
    at com.mapzen.android.lost.internal.FusedLocationProviderServiceImpl.reportLocation(FusedLocationProviderServiceImpl.java:126)
    at com.mapzen.android.lost.internal.FusionEngine.onLocationChanged(FusionEngine.java:191)
    at com.mapzen.android.lost.internal.FusionEngine.checkLastKnownAndNotify(FusionEngine.java:183)
    at com.mapzen.android.lost.internal.FusionEngine.checkLastKnownGps(FusionEngine.java:169)
    at com.mapzen.android.lost.internal.FusionEngine.enable(FusionEngine.java:119)
    at com.mapzen.android.lost.internal.LocationEngine.setRequest(LocationEngine.java:45)
    at com.mapzen.android.lost.internal.FusedLocationProviderServiceImpl.requestLocationUpdates(FusedLocationProviderServiceImpl.java:60)
    at com.mapzen.android.lost.internal.FusedLocationProviderService.requestLocationUpdates(FusedLocationProviderService.java:69)
    at com.mapzen.android.lost.internal.FusedLocationProviderApiImpl

This can be replicated by starting a separate Lost listener on another thread. Here's snippets from a minimal reproducing example (sorry for stuffing all the Lost stuff in one function :-/), based largely off of the example app. The initializeLocation() and initializeMap() calls are basically code from the example app that sets up LocationEngineListener and MapView.

I spin up a new thread and wait a few seconds to let MapView get set up, then I go ahead and register a second Lost listener independent of anything in the Mapbox SDK. When LocationSource.onLocationChanged picks up the updates from this separate thread you should crash and see the stacktrace above.

  @Override
  public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Mapbox.getInstance(this, getString(R.string.mapbox_token));
    setContentView(R.layout.activity_mapview);

    initializeLocation();
    initializeMap(savedInstanceState);

    Thread lostThread = new Thread() {
      public void run() {
        Looper.prepare();
        try {
          // Give main thread some time to get set up
          Thread.sleep(5000);
        } catch (InterruptedException ex) {}
        startLostRequest();
      }
    };
    lostThread.start();
  }

  private void startLostRequest() {
    Log.d("crash-example", "setting up lost");
    final LocationListener listener = new LocationListener() {
      public void onLocationChanged(Location location) {
        Log.d("crash-example", "lost location update on thread "  + Thread.currentThread().getId());
      }
      public void onProviderDisabled(String provider) { /* no-op */ }
      public void onProviderEnabled(String provider) { /* no-op */ }
    };
    final Object lock = new Object();
    Log.d("crash-example", "creating client");
    LostApiClient client = new LostApiClient.Builder(this)
      .addConnectionCallbacks(new LostApiClient.ConnectionCallbacks () {
        public void onConnected() {
          Log.d("crash-example", "lost client connected");
          synchronized(lock) {
            lock.notify();
          }
        }
        public void onConnectionSuspended() { /* no-op */ }
      })
      .build();
    client.connect();
    synchronized(lock) {
      if (!client.isConnected()) {
        try {
          lock.wait();
        } catch (InterruptedException ex) {}
      }
    }
    LocationRequest request = LocationRequest.create()
      .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
      .setInterval(1)
      .setSmallestDisplacement(0);
    LocationServices.FusedLocationApi.requestLocationUpdates(client, request, listener);
    Log.d("crash-example", "Lost updates requested");
  }
@tobrun tobrun added the Android Mapbox Maps SDK for Android label Apr 5, 2017
@chen-factual
Copy link

I've noticed that this only triggers if I invoke MapboxMap.setMyLocationEnabled(true), hope this helps you guys reproduce the issue.

@tobrun tobrun added this to the android-v5.1.0 milestone Apr 7, 2017
@tobrun tobrun added release blocker Blocks the next final release and removed release blocker Blocks the next final release labels Apr 24, 2017
@tobrun tobrun self-assigned this Apr 26, 2017
@tobrun
Copy link
Member

tobrun commented Apr 26, 2017

@chen-factual thank you for reaching out and reporting your issue. You can follow along progress on this ticket in the upstream issue in lostzen/lost#173. Another issue related to this is found in mapbox/mapbox-java#401. The workaround for now is not to start location request in another thread.

I'm going to remove release blocker label as this isn't an Mapbox Android SDK issue. Will be closing this when we upgrade to a newer version of our LOST dependency.

@zugaldia zugaldia added the release blocker Blocks the next final release label May 2, 2017
@zugaldia
Copy link
Member

zugaldia commented May 2, 2017

This has now been fixed upstream, I'm adding the release blocker tag hoping we can include the fix before 5.1 final (we're depending on LOST releasing 2.3 on time).

@zugaldia
Copy link
Member

zugaldia commented May 2, 2017

We'd also like to update our MAS dependency to the next release, where we also plan to update LOST. Work is tracked on mapbox/mapbox-java#401.

@ecgreb
Copy link

ecgreb commented May 2, 2017

This crash is now fixed in the latest Lost 2.3 SNAPSHOT.

Please note this is not a small set of changes to the library that will require a bit of testing plus there are a few other issues we want to have resolved in version 2.3. No release date has been set as of yet but we are working to get it released as quickly as possible. Thanks for everyone's patience!

@tobrun
Copy link
Member

tobrun commented May 22, 2017

Capturing from #8999 that this issue is resolved. Closing.

@tobrun tobrun closed this as completed May 22, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Android Mapbox Maps SDK for Android release blocker Blocks the next final release
Projects
None yet
Development

No branches or pull requests

5 participants