简体   繁体   English

谷歌地图海拔API android工作室

[英]Google Maps Elevation API android studio

I am creating an android app to record a user's activity using Google Maps SDK and the Google Play Services Location API.我正在创建一个 android 应用程序来使用 Google 地图 SDK 和 Google Play 服务位置 API 记录用户的活动。 I am attempting to retrieve the user's elevation based on a given latitude and longitude.我正在尝试根据给定的纬度和经度检索用户的海拔高度。 I originally used Location#getAltitude() but then realised that does not give the elevation above sea level.我最初使用 Location#getAltitude() 但后来意识到这并没有给出海拔高度。

I proceeded to use the open elevation API using the following query string:我使用以下查询字符串继续使用开放式高程 API:

String url = "https://api.open-elevation.com/api/v1/lookup?locations=" + latLng.latitude + "," + latLng.longitude;

However, that API appears to be much too slow in generating a response.但是,API 在生成响应方面似乎太慢了。 I then found the Google Maps Elevation API which we can make a request using a URL also.然后我找到了 Google Maps Elevation API,我们也可以使用 URL 提出请求。 However, we need to pass an API key and I do not want to pass this API key in the URL string and end up committing it to the remote repository.但是,我们需要传递一个 API 密钥,我不想在 URL 字符串中传递这个 API 密钥并最终将其提交到远程存储库。

In this repo ( https://github.com/googlemaps/google-maps-services-java ) I found the class: /src/main/java/com/google/maps/ElevationApi.java which I thought I could use to avoid messing around with http requests. In this repo ( https://github.com/googlemaps/google-maps-services-java ) I found the class: /src/main/java/com/google/maps/ElevationApi.java which I thought I could use to避免弄乱 http 请求。

In my gradle, I included this dependency:在我的 gradle 中,我包含了这个依赖项:

implementation 'com.google.maps:google-maps-services:0.18.0'

At the moment, the code to retrieve the elevation is as follows:目前,检索高程的代码如下:

ElevationApi.getByPoint(new GeoApiContext.Builder().apiKey(API_KEY).build(), latLng)
            .setCallback(new PendingResult.Callback<ElevationResult>() {
                @Override
                public void onResult(ElevationResult result) {
                    consumer.doAction(result.elevation);
                }

                @Override
                public void onFailure(Throwable e) {
                    e.printStackTrace();
                }
            });

What do I pass in for API_KEY here since I don't want to commit it to the repository?既然我不想将它提交到存储库,我应该在这里为 API_KEY 传递什么? I have an api key defined in local.properties for maps, however, like so:我在 local.properties 中为地图定义了一个 api 键,但是,如下所示:

MAPS_API_KEY=<API_KEY_HERE>

Basically, my question is, can I define an API key in a properties file that is not committed to GitHub and then reference it in the code?基本上,我的问题是,我可以在未提交给 GitHub 的属性文件中定义一个 API 键,然后在代码中引用它吗?

Thanks for any help.谢谢你的帮助。

Update: I have managed to read the API key from local.properties using gradle but got an exception from the ElevationApi saying API 21+ expected, but was 30...strange.更新:我已经设法使用 gradle 从 local.properties 读取 API 密钥,但从 ElevationApi 得到一个异常,说 API 21+ 预期,但是是 3。 So I went back to the open-elevation API with the following Volley request:所以我回到开放高度 API 并提出以下 Volley 请求:

/**
 * Calculates elevation gain for the provided recording service
 * @param recordingService the recording service to calculate elevation gain for
 * @param response the handler to consume the elevation gain with
 */
public static void calculateElevationGain(RecordingService recordingService, ActionHandlerConsumer<Double> response) {
    ArrayList<Location> locations = recordingService.getLocations();
    JSONArray array = constructLocations(locations);

    try {
        if (array != null) {
            RequestQueue requestQueue = Volley.newRequestQueue(recordingService);
            String url = "https://api.open-elevation.com/api/v1/lookup";
            JSONObject requestHeader = new JSONObject(); // TODO this seems very slow
            requestHeader.put("locations", array);
            JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, requestHeader,
                    response1 -> handleSuccessfulResponse(response1, response), RecordingUtils::handleErrorResponse);
            request.setRetryPolicy(new DefaultRetryPolicy(500000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
            requestQueue.add(request);
        }
    } catch (JSONException ex) {
        ex.printStackTrace();
    }
}

I had to set the timeout to a high number not sure how hight it should be because I was getting Volley timeout errors due to the slow response times.我不得不将超时设置为一个很大的数字,不确定它应该有多高,因为由于响应时间慢,我收到了 Volley 超时错误。

Are there any other ways I can retrieve elevation about sea level?还有其他方法可以检索有关海平面的高度吗?

Yeah, open-elevation.com has intermittent issues with timeouts and latency.是的,open-elevation.com 存在超时和延迟的间歇性问题。

There are some alternatives listed on this GIS stack exchange question Seeking alternative to Google Maps Elevation API .在这个 GIS 堆栈交换问题Seeking Alternative to Google Maps Elevation API中列出了一些替代方案。 I'm the developer of Open Topo Data which is the most-voted answer over there.我是Open Topo Data的开发人员,这是那里投票最多的答案。 You can host your own server with docker, and I also have a free public API which has pretty good latency and uptime.您可以使用 docker 托管您自己的服务器,我还有一个免费的公共 API,它具有相当好的延迟和正常运行时间。

There's also GPXZ as an alternative to the Google Elevation API with higher-quality data, but it requires an API key so would have the same issue as with Google Maps.还有GPXZ作为具有更高质量数据的 Google Elevation API 的替代品,但它需要 API 密钥,因此与 Google 地图存在相同的问题。

I advise a different direction: stay with the Google and the API key, but employ best practices regarding secrets and source repositories.我建议一个不同的方向:继续使用 Google 和 API 密钥,但采用有关机密和源存储库的最佳实践。 Since you are dealing with an Android app and not a webapp your key can be somewhat safe inside your app binary (versus a key in a web deployed app is exposed).由于您处理的是 Android 应用程序而不是 web 应用程序,因此您的密钥在您的应用程序二进制文件中可能有些安全(与 web 部署的应用程序中的密钥相比)。

Bets practices:投注做法:

  1. Do not commit the API key.不要提交 API 密钥。 The best to achieve this is to exclude the file which contains the key from the source control repo.实现这一点的最佳方法是从源代码管理存储库中排除包含密钥的文件。 That can simply be done with .gitignore .这可以简单地用.gitignore来完成。 For example this Codelab has a file with the secret , but it has a dummy value and normally this file should be excluded from the source.例如,这个 Codelab 有一个带有 secret 的文件,但它有一个虚拟值,通常应该从源中排除这个文件。 It is only there because that is an educational code lab.它只是在那里,因为那是一个教育代码实验室。
  2. As a security measure take advantage of GitGuardian to scan your repos in case you'd accidentally push an API key.作为一项安全措施,请利用GitGuardian扫描您的存储库,以防您意外按下 API 密钥。 In such events you'd get a notification.在这种情况下,您会收到通知。 As for me I forked that Geospatial API codelab and saw the key file was in the gitignore and I accidentally pushed a key.至于我,我分叉了 Geospatial API 代码实验室,看到密钥文件在 gitignore 中,我不小心按下了一个键。
  3. In case you accidentally push a key in a commit it's not enough to reverse the commit and delete the file.如果您在提交时不小心按下了某个键,仅撤销提交并删除文件是不够的。 Scavenger bots will still find the information in your git history.清道夫机器人仍会在您的 git 历史记录中找到信息。 Rather immediately disable the key and generate another one.而是立即禁用密钥并生成另一个密钥。
  4. If you are dealing with a webapp you can restrict the API key usage to your webapp's domain.如果您正在处理 web 应用程序,您可以将 API 密钥使用限制在您的 web 应用程序的域中。 Similarly you can restrict the key to specific Android app signatures (don't forget to add your developer environment's signature) too.同样,您也可以将密钥限制为特定的 Android 应用程序签名(不要忘记添加您的开发人员环境的签名)。 This guarantees that even if someone steals the key they probably won't be able to use it.这保证了即使有人窃取了密钥,他们也可能无法使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM