I'm making use of the new Android Google Maps API.
I create an activity which includes a MapFragment. In the activity onResume
I set the markers into the GoogleMap object and then define a bounding box for the map which includes all of the markers.
This is using the following pseudo code:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
while(data) {
LatLng latlng = getPosition();
builder.include(latlng);
}
CameraUpdate cameraUpdate = CameraUpdateFactory
.newLatLngBounds(builder.build(), 10);
map.moveCamera(cameraUpdate);
The call to map.moveCamera()
causes my application to crash with the following stack:
Caused by: java.lang.IllegalStateException:
Map size should not be 0. Most likely, layout has not yet
at maps.am.r.b(Unknown Source)
at maps.y.q.a(Unknown Source)
at maps.y.au.a(Unknown Source)
at maps.y.ae.moveCamera(Unknown Source)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$Stub
.onTransact(IGoogleMapDelegate.java:83)
at android.os.Binder.transact(Binder.java:310)
at com.google.android.gms.maps.internal.IGoogleMapDelegate$a$a
.moveCamera(Unknown Source)
at com.google.android.gms.maps.GoogleMap.moveCamera(Unknown Source)
at ShowMapActivity.drawMapMarkers(ShowMapActivity.java:91)
at ShowMapActivity.onResume(ShowMapActivity.java:58)
at android.app.Instrumentation
.callActivityOnResume(Instrumentation.java:1185)
at android.app.Activity.performResume(Activity.java:5182)
at android.app.ActivityThread
.performResumeActivity(ActivityThread.java:2732)
If - instead of the newLatLngBounds()
factory method I use newLatLngZoom()
method then the same trap does not occur.
Is the onResume
the best place to draw the markers onto the GoogleMap object or should I be drawing the markers and setting the camera position somewhere else?
The solution is simpler than that....
Catch
IllegalStateException
and use the global listener on the view instead. Setting the bound size in advance (pre-layout) using the other methods means you have to compute the size of THE VIEW, not the screen device. They only match if you go full screen with your map and do not use fragments.In very rare cases, MapView layout is finished, but GoogleMap layout is not finished,
ViewTreeObserver.OnGlobalLayoutListener
itself can't stop the crash. I saw the crash with Google Play services package version 5084032. This rare case may be caused by the dynamic change of the visibility of my MapView.To solve this problem, I embedded
GoogleMap.OnMapLoadedCallback
inonGlobalLayout()
,This is my fix, just wait untill the map is loaded in that case.
I've created a way to combine the two callbacks: onMapReady and onGlobalLayout into one single observable which will emit only when both the events have been triggered.
https://gist.github.com/abhaysood/e275b3d0937f297980d14b439a8e0d4a
Why not just use something like this:
There is a helper class in the Google Maps repo that you can leverage - it waits for both the layout and map to be ready before notifying a callback with the GoogleMap:
The original source is here:
https://github.com/googlemaps/android-samples/blob/7ee737b8fd6d39c77f8b3716ba948e1ce3730e61/ApiDemos/java/app/src/main/java/com/example/mapdemo/OnMapAndViewReadyListener.java
There is a Kotlin implementation too:
https://github.com/googlemaps/android-samples/blob/master/ApiDemos/kotlin/app/src/main/java/com/example/kotlindemos/OnMapAndViewReadyListener.kt