Issue with Google Maps toScreenLocation() method Android

2.5k views Asked by At

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.

1

There are 1 answers

3
bjiang On BEST ANSWER

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.