【问题标题】:How to check if position if valid in StreetView in Android如何检查Android街景中的位置是否有效
【发布时间】:2013-06-17 14:33:55
【问题描述】:

我有一个应用程序根据定义的边界在 GoogleMaps 中随机生成位置。因此,我首先生成一个随机 LatLng,然后验证该点是否在我的边界内。如果是,则有效。

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();

因此,在此之后,我得到了有效点。我的问题是谷歌地图中的有效点在街景中不一定有效。

这个随机点可能位于地球上尚未在街景中映射的某个位置。我也需要它在那里有效。

我知道您可以使用 link 之后的 JavaScript API v3 来完成此操作。

你会这样做:

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
                }
            });

但我希望仅使用 Android 来执行此操作。顺便说一下,我使用的是 Google Play Services API,不是 Google Maps v2 Android。

谁能解释一下?

编辑: 按照ratana的建议,这是我目前所拥有的:

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());
            }
        });

【问题讨论】:

标签: android google-maps-api-3


【解决方案1】:
@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
    }
}
 });

编辑:谷歌的官方答案在这里 (https://code.google.com/p/gmaps-api-issues/issues/detail?id=7033),它指向这里: https://code.google.com/p/gmaps-api-issues/issues/detail?id=4823

官方解决方案是通过 HTTPS 使用官方的 Google Street View Image API(免费,无限制 - https://developers.google.com/maps/documentation/streetview/metadata)。

旧(已弃用)答案:

我已经为此拼凑了一个变通方法,虽然丑陋但保留在 API 中,直到 Google 更新它以允许像 iOS SDK 那样查询全景图。

这涉及创建StreetViewPanoramaView,但不将其附加到布局,并将其位置设置为当前位置。然后测试它是否有一个全景位置。

这似乎可行,但将在 Android Google Maps API V2(它是 google play services API 的一部分)跟踪器上提交请求以添加此功能,因为 iOS SDK 具有此功能。

// 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);

编辑:使用新的 Async API 调用:

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

【讨论】:

  • 功能请求现在在谷歌的问题跟踪器中 - 请在那里加注星标 -- google maps api issue tracker
  • 这可能是迄今为止最好的解决方案。
  • 我一直在努力让它工作,但到目前为止还没有运气。我看到 getStreetViewPanorama 已被弃用,现在应该使用 getStreetViewPanoramaAsync() 。我正在尝试这个,但条件 if (svpView.getStreetViewPanorama().getLocation() != null) 总是错误的。即使我 100% 确定我正在测试一个在全景图中有效的位置。有什么提示吗?
  • 非常感谢您的代码。它现在肯定有效。我必须对其进行更改,因为我有一个带有随机 LatLng 点的 ArrayList,所以我需要遍历整个列表,但需要先等待 postDelayed 完成,然后再移动到下一个项目。我已将这段代码包含在我的原始帖子中。它没有像预期的那样工作。我在处理线程时遇到了困难。不过非常感谢。
  • 另请参阅 code.google.com/p/gmaps-api-issues/issues/detail?id=7033 以了解新的(并且可能更好的)解决方法。
【解决方案2】:

我为这个问题搜索了很多。最后我得到了一个有用的链接。请参阅在 android api 中没有直接使用 getPanoramaByLocation() javascript 函数的方法。但是有一个解决方法。

这里我提供网址:

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

查看案例:

  1. 当您通过提供有效的纬度/经度点击此网址时。你会得到街景。因此,您可以使用该图像大小或内容来检查它是空白图像还是有效图像。

查看此网址:

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

  1. 在上面的 url 中,我传递了无效的 lat/lng,这意味着对于这个 lat/lng,没有街景,因此您可以使用“文本提取库”或检查文件大小。届时您将了解街景是否可用

当您点击 url 获取街景时,请检查此链接以获取响应:

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

【讨论】:

  • 不错的尝试,但恕我直言,请求图像(尺寸为 50x50 像素的图像至少 2 KB)仅用于检查街景是否可用并不是一个好主意。
  • 我不确定,但必须有一种方法可以通过传递宽度/高度来获得小尺寸图像。所以尺寸会缩小。
  • 这确实是一个很好的尝试,但我会谨慎行事。想象一下,如果我生成 1000 个随机点,而所有这些点碰巧在街景视图中都无效?我的应用程序中的用户体验会很糟糕:(我仍然没有找到一个好的解决方案。
  • 我会为您的最后一条评论推荐缓存机制。所以它可能会带你到目的地。
  • @AlexVogel & Felipe Caldas 根据您的最后评论,您接受我的回答吗?
【解决方案3】:

我创建了一个小型库(基于 VVB's answer),它可以让您(非常可靠地)检查 StreetView 是否可用于特定位置。

Feel free to check it out.

【讨论】:

    【解决方案4】:
    1. 验证可用的全景视图

      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");                            
                      }
                  }
              });
          }
      });
      

    【讨论】:

    • 您可以在答案中添加更多详细信息吗?
    【解决方案5】:

    对于我的街景应用,我构建了一个抓取应用作为伴侣,这个抓取应用遍历给定半径内的所有纬度/经度位置,并在街景中查询全景图。

    这个应用程序的输出是一个包含 lat/lng 位置的小文本文件,其分辨率适合我的需要(5 度)。然后,我在我的主应用程序中使用此数据文件作为街景位置的来源。

    使用 setPostion(LatLng, radius) 方法,我保证每次都能得到结果。这个文件的大小也很小

    我怀疑 Google 是否会发布街景所在位置的数据集(我在每次更新主应用程序之前运行我的抓取应用程序,以确保我有最新的值)。我不确定他们是否会提供具有以下签名的方法 boolean hasStreetView(LatLng, radius)。

    【讨论】:

    • 您有机会分享您的抓取应用程序的代码吗?
    • 抱歉@FelipeCaldas,我无法分享代码,但它会为地球上的每个地点生成 LatLng 坐标,并检查该位置是否有街景图像。 radius 参数用于计算我生成的网格的大小,并将相同的半径传递给 streetview 方法。
    • 嘿安德鲁·凯利。没关系,谢谢。我正在使用代码生成随机 LatLng,并且工作正常。我在谷歌地图中测试的所有点实际上都是有效的,甚至在我定义的范围内。问题是当我使用@ratana 代码尝试验证 Panaroma 中的点时。它总是返回 null 给我。我让它运行了一个小时,甚至没有生成一个有效点。我心碎了 :) 我什至现在正在考虑使用与 PHP 集成的 JS Maps API 创建一个 javascript 页面来为我提供该数据。我只是不知道该怎么做:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 2011-06-21
    相关资源
    最近更新 更多