Why does GoogleMap.animateCamera () crash after onGlobalLayout ()?

I have a problem with a snippet that embeds a SuportMapFragment from the new Google Maps API. When my fragment is created, it retrieves some data in AsyncTask , starting with the onResume method. While this happens, MapFragment remains off-screen, and a progress bar is displayed instead.

When AsyncTask complete, I log in with the onGlobalLayout mapView event. Then I show a fragment that leads to the display and display of the map view. onGlobalLayout starts and the animation starts.

This worked fine for some time, until I started optimizing AsyncTask data collection AsyncTask for completion almost instantly. Now the application will often crash on startup, more often in Release than Debug, so I think I'm dealing with a racing condition here that I don't know about.

An exception:

The size of the map should not be 0. Most likely, the layout has not yet appeared to display the map.

Any ideas are greatly appreciated.

For reference: this is the code that seems to be causing the crash:

 // Hide status UI this.progressBar.setVisibility(View.INVISIBLE); this.statusTextView.setVisibility(View.INVISIBLE); // Update state this.uraDataDownloadFinished = true; // Schedule map translation to occur when layout is complete final View mapView = this.mapFragment.getView(); if (mapView.getViewTreeObserver().isAlive()) { mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @SuppressLint("NewApi") // We check which build version we are using. @Override public void onGlobalLayout() { Log.d(TAG, "onGlobalLayout()"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } // here we crash this.map.animateCamera( CameraUpdateFactory.newLatLngBounds( LatLngBounds.builder() .include(topLeft) .include(topRight) .include(bottomLeft) .include(bottomRight) .build(), 0), durationMs, null); } }); } // Show map (which will eventually trigger onGlobalLayout) this.getFragmentManager().beginTransaction().show(this.mapFragment).commit(); this.mapFragment.getMap().setOnCameraChangeListener(this); 

Thank you so much!

+7
source share
2 answers

I'm not sure, but since you are using AsyncTask, you are probably trying to get maps before the map has undergone a layout.

You can see the documentation , suggesting instead use newLatLngBounds(boundary, width, height, padding) .

+5
source

Try this, it works for me:

 map.setOnCameraChangeListener(new OnCameraChangeListener() { @Override public void onCameraChange(CameraPosition arg0) { // Move camera. map.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 10)); // Remove listener to prevent position reset on camera move. map.setOnCameraChangeListener(null); } }); 
+3
source

All Articles