15

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());
            }
        });
Rot-man
  • 18,045
  • 12
  • 118
  • 124
Felipe Caldas
  • 2,492
  • 3
  • 36
  • 55
  • Possibly Duplicate of : http://stackoverflow.com/questions/23909623/how-to-check-is-streetview-is-available-on-location – VVB Jul 31 '14 at 13:07
  • See also https://code.google.com/p/gmaps-api-issues/issues/detail?id=7033 for a new (and likely better) workaround. – miguev Nov 25 '16 at 11:11

5 Answers5

6
@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);

TeeTracker
  • 7,064
  • 8
  • 40
  • 46
ratana
  • 175
  • 3
  • 12
  • feature request is now in google's issue tracker - please star it there -- [google maps api issue tracker](https://code.google.com/p/gmaps-api-issues/issues/detail?id=7033) – ratana Aug 23 '14 at 02:48
  • 1
    This is probably the best solution so far. – Felipe Caldas Jan 01 '15 at 10:49
  • 1
    I have been trying to get this working but not luck so far. I see that the getStreetViewPanorama is deprecated and one should use getStreetViewPanoramaAsync() now. I am trying this but the condition if (svpView.getStreetViewPanorama().getLocation() != null) is always false. Even though I am 100% sure I am testing a location valid in a Panorama. Any hints? – Felipe Caldas Feb 07 '15 at 02:01
  • 1
    thank you very much for your code. It definitely works now. I had to make changes to it because I have an ArrayList with random LatLng points, so I need to iterate over that whole list but need first to wait for the postDelayed to finish before moving to the next item. I've included the piece of code to my original post. It's not working as good as expected. I am having difficulties handling the threads. Thanks a lot though. – Felipe Caldas Feb 08 '15 at 08:07
  • 1
    See also code.google.com/p/gmaps-api-issues/issues/detail?id=7033 for a new (and likely better) workaround. – miguev Nov 25 '16 at 11:11
5

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

VVB
  • 7,363
  • 7
  • 49
  • 83
  • Nice attempt, but it IMHO it's not a good idea to request a image (with at least 2 KB for image with size 50x50 px) only for checking if streetview is available. – AlexVogel Aug 01 '14 at 13:21
  • I'm not sure but there must be a way to get small size image by passing width/height. So size will be down scaled. – VVB Aug 01 '14 at 13:24
  • It's a good attempt indeed, but I would exercise caution with it. Imagine if I generate 1000 random points and all of them happen not to be valid in Street Views? The UX in my app would be hideous :( I still have not managed to find a good solution for this. – Felipe Caldas Aug 04 '14 at 12:35
  • I will recommend cache mechanism for your last comment. So it might take you to your destination. – VVB Aug 06 '14 at 04:19
  • @AlexVogel & Felipe Caldas As per your last comment, Do you accept my answer? – VVB Aug 06 '14 at 04:42
  • See also code.google.com/p/gmaps-api-issues/issues/detail?id=7033 for a new (and likely better) workaround. – miguev Nov 25 '16 at 11:11
3

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

Community
  • 1
  • 1
Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
1
  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");                            
                    }
                }
            });
        }
    });
    
0

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).

Andrew Kelly
  • 2,180
  • 2
  • 19
  • 27
  • Any chances you could share the code of your scraping app? – Felipe Caldas Feb 01 '15 at 02:18
  • Sorry @FelipeCaldas, I can't share the code, but all it does it generate LatLng coordinates for every spot on the globe and checks to see if there is a StreetView image at that location. The radius parameter is used to calculate the size of the grid I generate and the same radius is passed to the streetview method. – Andrew Kelly Feb 01 '15 at 22:28
  • Hey Andrew Kelly. That's alright, thank you. I am using a code to generate random LatLng and that is working fine. All points I test in Google Maps are actually valid and even within the bounds I defined. The problem is when I use @ratana code to try to valid the point in a Panaroma. It always returns null to me. I left it running for one hour and not even one single valid point was generated. I am heart broken :) I am even now considering creating a javascript page using the JS Maps API integrated with PHP to give me that data. I just dont know how to do that yet :) – Felipe Caldas Feb 03 '15 at 11:25