Felipe Caldas
Felipe Caldas

Reputation: 2503

How to check if position if valid in StreetView in Android

I have an app that is randomly generating positions in a GoogleMaps based on a defined boundary. So I first generate a random LatLng and then I verify if this point is inside my boundary. If it is, it's valid.

Builder builder = new LatLngBounds.Builder();

        double antartica[] = {-62.5670958528642, -59.92767333984375, -62.584805850293485, -59.98260498046875, -62.61450963659083};
        for (int i = 0; i < antartica.length; i++) {
            builder.include(new LatLng(antartica[i],antartica[++i]));
        }
        pAntarctica = builder.build();

LatLng point = generateRandomPosition();
    if(isWithinBoundaries(point))
        return point;
    else
        return getValidPoint();

So after this, I end up with the valid point. My problem is that a valid point in Google Maps is not necessarily valid in StreetView.

It might happen that this random point is somewhere in the globe not yet mapped in StreetView. I need it to be valid there as well.

I am aware that you can accomplish this using the JavaScript API v3 following this link.

You would do something like this:

var latLng = new google.maps.LatLng(12.121221, 78.121212);
            streetViewService.getPanoramaByLocation(latLng, STREETVIEW_MAX_DISTANCE, function (streetViewPanoramaData, status) {
                if (status === google.maps.StreetViewStatus.OK) {
                    //ok
                } else {
                    //no ok
                }
            });

But I am hoping to do this using Android only. I am using the Google Play Services API by the way, and not the Google Maps v2 Android.

Can anyone shed some light?

EDIT: Following ratana's suggestion, this is what I have so far:

svpView.getStreetViewPanoramaAsync(new OnStreetViewPanoramaReadyCallback() {
            @Override
            public void onStreetViewPanoramaReady(final StreetViewPanorama panorama) {
                for(final LatLng point : points) {
                    System.out.println(point.latitude + " " + point.longitude);     
                    panorama.setPosition(point, 1000);

                    final CountDownLatch latch = new CountDownLatch(1);

                    mHandlerMaps.post(new Runnable() {
                        @Override
                        public void run() {
                            if (panorama.getLocation() != null) {
                                System.out.println("not null " + panorama.getLocation().position);
                                writeToFile(panorama.getLocation().position.toString());
                                l.add(point);
                            }
                            latch.countDown();
                        }
                    });

                    try {
                        latch.await(4, TimeUnit.SECONDS);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(l.toString());
            }
        });

Upvotes: 15

Views: 5705

Answers (5)

Nilton Rodriguez
Nilton Rodriguez

Reputation: 21

  1. validate panoramic view available:

    mStreetViewPanoramaView.getStreetViewPanoramaAsync(new OnStreetViewPanoramaReadyCallback() {
        @Override
        public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
            //Using setPositionWithRadius
            streetViewPanorama.setPosition(new LatLng(latitud, longitud), 200);
            mPanorama = streetViewPanorama;
    
            mPanorama.setOnStreetViewPanoramaChangeListener(new StreetViewPanorama.OnStreetViewPanoramaChangeListener() {
                @Override
                public void onStreetViewPanoramaChange(StreetViewPanoramaLocation streetViewPanoramaLocation) {
                    if (streetViewPanoramaLocation == null) {                            
                        Log.e("StreetViewActivity","Panoramic view not available");                            
                    }
                }
            });
        }
    });
    

Upvotes: 1

ratana
ratana

Reputation: 175

@Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
    mPanorama.setOnStreetViewPanoramaChangeListener(new StreetViewPanorama.OnStreetViewPanoramaChangeListener() {
@Override
public void onStreetViewPanoramaChange(StreetViewPanoramaLocation streetViewPanoramaLocation) {
    if (streetViewPanoramaLocation != null && streetViewPanoramaLocation.links != null) {
        // location is present
    } else {
        // location not available
    }
}
 });

EDIT: Google's official answer is here (https://code.google.com/p/gmaps-api-issues/issues/detail?id=7033), which points here: https://code.google.com/p/gmaps-api-issues/issues/detail?id=4823

The official solution involves using the official Google Street View Image API (free, no limit - https://developers.google.com/maps/documentation/streetview/metadata) via HTTPS.

OLD (DEPRECATED) ANSWER:

I've hacked together a workaround for this that is ugly but stays within the API, until Google updates it to allow querying for panoramas the way the iOS SDK does.

This involves creating a StreetViewPanoramaView, but not attaching it to the layout, and setting its position to the current location. And then testing if it has a panorama location following that.

This seems to work, but will be filing a request on the Android Google Maps API V2 (Which is part of the google play services API) tracker to add this, since the iOS SDK has this capability.

// Handle on the panorama view
private StreetViewPanoramaView svpView;

...

// create a StreetViewPanoramaView in your fragment onCreateView or activity onCreate method
// make sure to handle its lifecycle methods with the fragment or activity's as per the documentation - onResume, onPause, onDestroy, onSaveInstanceState, etc.
StreetViewPanoramaOptions options = new StreetViewPanoramaOptions();
svpView = new StreetViewPanoramaView(getActivity(), options);
svpView.onCreate(savedInstanceState);

...

// Snippet for when the map's location changes, query for street view panorama existence
private Handler mHandler = new Handler();
private static final int QUERY_DELAY_MS = 500;

// When the map's location changes, set the panorama position to the map location
svpView.getStreetViewPanorama().setPosition(mapLocationLatLng);

mHandler.postDelayed(new Runnable() {
    @Override
    public void run() {
        if (svpView.getStreetViewPanorama().getLocation() != null) {
            // YOUR DESIRED ACTION HERE -- get the panoramaID, etc..
            // getLocation() -- a StreetViewPanoramaLocation -- will be null if there is no panorama
            // We have to delay this a bit because it may take some time before it loads
            // Note that adding an OnStreetViewPanoramaChangeListener doesn't seem to be reliably called after setPosition is called and there is a panorama -- possibly because it's not been added to the layout?
        }
    }
}, QUERY_DELAY_MS);

EDIT: to use the new Async API call:

svpView.getStreetViewPanoramaAsync(new OnStreetViewPanoramaReadyCallback() {
    @Override
    public void onStreetViewPanoramaReady(final StreetViewPanorama panorama) {
        panorama.setPosition(mapLocationLatLng, DEFAULT_SEARCH_RADIUS);
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (panorama.getLocation() != null) {
                    // your actions here
                }
            }
        }, QUERY_DELAY_MS);

Upvotes: 6

Bartek Lipinski
Bartek Lipinski

Reputation: 31438

I've created a small library (based on VVB's answer), that lets you (pretty reliably) check if StreetView is available for a specific location.

Feel free to check it out.

StreetViewProbe

Upvotes: 3

Andrew Kelly
Andrew Kelly

Reputation: 2188

For my StreetView app I built a scraping app as a companion, this scraping app goes through all the lat/lng locations at a given radius and queries StreetView for a panorama.

The output of this app is a small text file of lat/lng locations at a resolution suitable for my needs (5 degrees). I then use this data file in my main app as a source for StreetView locations.

Using the setPostion(LatLng, radius) method I'm guaranteed to get a result every time. The size of this file is also quite small < 500kb.

I doubt Google will ever release a dataset of where StreetView has been (I run my scraping app just before each update to my main app to make sure I have up to date values). I'm not sure if they'd provide a method that has the following signature either boolean hasStreetView(LatLng, radius).

Upvotes: 0

VVB
VVB

Reputation: 7641

I google a lot for this question. Finally I got one useful link. See there is no direct way to use getPanoramaByLocation() javascript function in android api. But there is a work around to this.

Here I'm providing url :

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=40.720032,-73.988354&fov=90&heading=235&pitch=10

See cases :

  1. When you hit this url by providing valid lat/lng. You will get streetview. So you can use that image size or contents for checking whether its a blank image or valid image.

See this url :

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=73.67868,-73.988354&fov=90&heading=235&pitch=10

  1. In above url I passed invalid lat/lng means this for this lat/lng there is no streetview so you can either use "text extract library" or by checking file size. You will get to know whether streetview is available or not for that point

Check this link for response when you hit url for fetching streetview :

https://developers.google.com/maps/documentation/geocoding/?hl=nl

Upvotes: 5

Related Questions