Search code examples
androidgoogle-mapsopengl-es-2.0google-maps-api-2

Issue with Google Maps toScreenLocation() method Android


As the title mentions, I'm having issues with the toScreenLocation() with Google Maps.

I'm trying to pick arbitrary points on Google Maps that I am broadcasting to my Google Maps fragment. Within the fragment, I want to get the Screen Point this LatLng coordinate corresponds with. However, most of the time I get an error like the following:

Caused by: java.lang.IllegalArgumentException: left == right
        at android.opengl.Matrix.frustumM(Matrix.java:327)
        at com.google.maps.api.android.lib6.gmm6.o.b.b.j(Unknown Source)
        at com.google.maps.api.android.lib6.gmm6.o.b.b.l(Unknown Source)
        at com.google.maps.api.android.lib6.gmm6.o.b.b.a(Unknown Source)
        at com.google.maps.api.android.lib6.gmm6.o.b.b.c(Unknown Source)
        at com.google.maps.api.android.lib6.gmm6.c.y.a(Unknown Source)
        at com.google.maps.api.android.lib6.c.az.a(Unknown Source)
        at com.google.android.gms.maps.internal.ca.onTransact(SourceFile:74)
        at android.os.Binder.transact(Binder.java:380)
        at com.google.android.gms.maps.internal.IProjectionDelegate$zza$zza.toScreenLocation(Unknown Source)
        at com.google.android.gms.maps.Projection.toScreenLocation(Unknown Source)
        at com.example.tracker.googlemaps.GoogleMapsTracker.convertCoordinates(GoogleMapsTracker.java:163)
        at com.example.tracker.googlemaps.GoogleMapsTracker.access$100(GoogleMapsTracker.java:38)
        at com.example.tracker.googlemaps.GoogleMapsTracker$2.onReceive(GoogleMapsTracker.java:153)
        at     android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:866)

The code that corresponds with the conversion is:

    private void convertCoordinates(float latitude, float longitude){
    location = new LatLng(latitude, longitude);
    if(location.latitude != (float) 0.0 || location.longitude != (float) 0.0){
        //Point map = mapView.getMap().getProjection().toScreenLocation(location);

        Point map = projection.toScreenLocation(location);
        ScreenAdjustments.setLati(map.y);
        ScreenAdjustments.setLongi(map.x);
    } else {
        Log.e(TAG, "BAD COORDINATES!!!");
    }
}

I have verified that I am getting in float values and that they are what I hard coded them to be. But most of the time when it hits the Point map = projection.toScreenLocation(location); it will throw the error about the frustum.

I need help in figuring out how to get this to work.


Solution

  • I first tried your code and got no error.

    According to here, I tired toScreenLocation and it works. Remember set OnGlobalLayoutListener to make sure the map view and waiting for layout process to settle.

    Sample code:

    public class MainActivity extends FragmentActivity {
    
        GoogleMap mGoogleMap;
        private static LatLng MountainView = new LatLng(37.42, -122.08);
        private static LatLng MountainView2 = new LatLng(37.421, -122.081);
        View mapView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            // Initial Map
            try {
    
                if (mGoogleMap == null) {
                    mGoogleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
    
            mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
            mGoogleMap.getUiSettings().setZoomControlsEnabled(true);
            mGoogleMap.getUiSettings().setZoomGesturesEnabled(true);
    
            //mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(MountainView, 15));
    
            Marker marker = mGoogleMap.addMarker(new MarkerOptions()
                    .position(MountainView)
                    .title("Have a nice day!"));
    
            convertCoordinates((float) 37.42, (float) -122.08);
    
        }
    
        private void convertCoordinates(float latitude, float longitude) {
            final LatLng location = new LatLng(latitude, longitude);
            if (location.latitude != (float) 0.0 || location.longitude != (float) 0.0) {
                if (mapView.getViewTreeObserver().isAlive()) {
                    mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            // remove the listener
                            // ! before Jelly Bean:
                            mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                            // ! for Jelly Bean and later:
                            //mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                            // set map viewport
                            // CENTER is LatLng object with the center of the map
                            mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 15));
                            // ! you can query Projection object here
                            Point markerScreenPosition = mGoogleMap.getProjection().toScreenLocation(location);
                            // ! example output in my test code: (356, 483)
                            Log.d("x!!!!", markerScreenPosition.x + "");
                            Log.d("y!!!!", markerScreenPosition.y + "");
                        }
                    });
    
                } else {
                    //Log.e(TAG, "BAD COORDINATES!!!");
                }
            }
        }
    }
    

    It works and output is x = 639, y = 1049 on my Nexus 6.