Google place api 在 Android 中显示错误

2023-12-15

我在这里面临一个奇怪的问题。

我想从我的 Android 应用程序查询 google 地点网络服务。

为此,我总是收到错误:“此服务需要 API 密钥”。

然而,当我尝试使用 Chrome 浏览器和服务器密钥查询它时,我得到了正确的响应。

对于 android,我应该使用哪个密钥作为 android api 密钥给我这个错误。

添加包名称是可选的:

See here

This is the screenshot of the enabled api(s) for my app

Edit

这是请求网址:

https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=cruise&key=AIzaSyDeFunLJQLF7WInuNnaWfbeyJzfw_1litQ

当我在浏览器中运行这个时,我得到这个:

Running in Chrome browser

使用 hurl.it 发送相同的请求:

Screen-1

Screen-2

我收到 @android 应用程序的确切错误。


对于 Google Places Web API,您需要使用服务器密钥。

从技术上讲,该 API 并不适合在客户端应用程序中使用,它是为网站使用而设计的。

您可以在应用程序中使用它,但是您将需要使用不安全的服务器密钥。

如果你看文档,它明确指出:

注意:Google Places API Web 服务不适用于 Android 或 iOS API 密钥。

官方说明:

或者,按照以下步骤获取 API 密钥:

转到 Google 开发者控制台。

创建或选择一个项目。

单击继续以启用 API。

转到凭据以获取服务器密钥(并设置 API 凭据)。

为了防止配额被盗,请遵循这些最佳实践来保护您的 API 密钥。 (可选)启用计费。有关详细信息,请参阅使用限制和计费。

重要提示:将 IP 地址字段留空,以便直接从应用程序使用此 Web 服务 API:

enter image description here

编辑:这是正在运行和测试的 Activity 的完整代码,您可以将其用作参考以查看代码中是否存在问题:

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class MapsActivity2 extends AppCompatActivity implements OnMapReadyCallback
{
    private GoogleMap mGoogleMap;
    SupportMapFragment mapFrag;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        //Use this one:
        setContentView(R.layout.activity_maps2);

        mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFrag.getMapAsync(this);

    }

    @Override
    public void onMapReady(GoogleMap googleMap)
    {
        mGoogleMap=googleMap;
        mGoogleMap.setMyLocationEnabled(true);
        StringBuilder sbValue = new StringBuilder(sbMethod());
        PlacesTask placesTask = new PlacesTask();
        placesTask.execute(sbValue.toString());
    }

    public StringBuilder sbMethod()
    {

        //use your current location here
        double mLatitude = 37.77657;
        double mLongitude = -122.417506;

        StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
        sb.append("location=" + mLatitude + "," + mLongitude);
        sb.append("&radius=5000");
        sb.append("&types=" + "restaurant");
        sb.append("&sensor=true");

        sb.append("&key=AIza******************************");

        Log.d("Map", "url: " + sb.toString());

        return sb;
    }

    private class PlacesTask extends AsyncTask<String, Integer, String>
    {

        String data = null;

        // Invoked by execute() method of this object
        @Override
        protected String doInBackground(String... url) {
            try {
                data = downloadUrl(url[0]);
            } catch (Exception e) {
                Log.d("Background Task", e.toString());
            }
            return data;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(String result) {
            ParserTask parserTask = new ParserTask();

            // Start parsing the Google places in JSON format
            // Invokes the "doInBackground()" method of the class ParserTask
            parserTask.execute(result);
        }
    }

    private String downloadUrl(String strUrl) throws IOException
    {
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(strUrl);

            // Creating an http connection to communicate with url
            urlConnection = (HttpURLConnection) url.openConnection();

            // Connecting to url
            urlConnection.connect();

            // Reading data from url
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

            StringBuffer sb = new StringBuffer();

            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            data = sb.toString();

            br.close();

        } catch (Exception e) {
            Log.d("Exception", e.toString());
        } finally {
            iStream.close();
            urlConnection.disconnect();
        }
        return data;
    }

    private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String, String>>> {

        JSONObject jObject;

        // Invoked by execute() method of this object
        @Override
        protected List<HashMap<String, String>> doInBackground(String... jsonData) {

            List<HashMap<String, String>> places = null;
            Place_JSON placeJson = new Place_JSON();

            try {
                jObject = new JSONObject(jsonData[0]);

                places = placeJson.parse(jObject);

            } catch (Exception e) {
                Log.d("Exception", e.toString());
            }
            return places;
        }

        // Executed after the complete execution of doInBackground() method
        @Override
        protected void onPostExecute(List<HashMap<String, String>> list) {

            Log.d("Map", "list size: " + list.size());
            // Clears all the existing markers;
            mGoogleMap.clear();

            for (int i = 0; i < list.size(); i++) {

                // Creating a marker
                MarkerOptions markerOptions = new MarkerOptions();

                // Getting a place from the places list
                HashMap<String, String> hmPlace = list.get(i);


                // Getting latitude of the place
                double lat = Double.parseDouble(hmPlace.get("lat"));

                // Getting longitude of the place
                double lng = Double.parseDouble(hmPlace.get("lng"));

                // Getting name
                String name = hmPlace.get("place_name");

                Log.d("Map", "place: " + name);

                // Getting vicinity
                String vicinity = hmPlace.get("vicinity");

                LatLng latLng = new LatLng(lat, lng);

                // Setting the position for the marker
                markerOptions.position(latLng);

                markerOptions.title(name + " : " + vicinity);

                markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));

                // Placing a marker on the touched position
                Marker m = mGoogleMap.addMarker(markerOptions);

            }
        }
    }
    public class Place_JSON {

        /**
         * Receives a JSONObject and returns a list
         */
        public List<HashMap<String, String>> parse(JSONObject jObject) {

            JSONArray jPlaces = null;
            try {
                /** Retrieves all the elements in the 'places' array */
                jPlaces = jObject.getJSONArray("results");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            /** Invoking getPlaces with the array of json object
             * where each json object represent a place
             */
            return getPlaces(jPlaces);
        }

        private List<HashMap<String, String>> getPlaces(JSONArray jPlaces) {
            int placesCount = jPlaces.length();
            List<HashMap<String, String>> placesList = new ArrayList<HashMap<String, String>>();
            HashMap<String, String> place = null;

            /** Taking each place, parses and adds to list object */
            for (int i = 0; i < placesCount; i++) {
                try {
                    /** Call getPlace with place JSON object to parse the place */
                    place = getPlace((JSONObject) jPlaces.get(i));
                    placesList.add(place);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            return placesList;
        }

        /**
         * Parsing the Place JSON object
         */
        private HashMap<String, String> getPlace(JSONObject jPlace)
        {

            HashMap<String, String> place = new HashMap<String, String>();
            String placeName = "-NA-";
            String vicinity = "-NA-";
            String latitude = "";
            String longitude = "";
            String reference = "";

            try {
                // Extracting Place name, if available
                if (!jPlace.isNull("name")) {
                    placeName = jPlace.getString("name");
                }

                // Extracting Place Vicinity, if available
                if (!jPlace.isNull("vicinity")) {
                    vicinity = jPlace.getString("vicinity");
                }

                latitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
                longitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");
                reference = jPlace.getString("reference");

                place.put("place_name", placeName);
                place.put("vicinity", vicinity);
                place.put("lat", latitude);
                place.put("lng", longitude);
                place.put("reference", reference);

            } catch (JSONException e) {
                e.printStackTrace();
            }
            return place;
        }
    }

}

活动地图2.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:map="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"
        tools:context="com.iotaconcepts.aurum.MapsActivity2"
        android:name="com.google.android.gms.maps.SupportMapFragment"/>

</LinearLayout>

Result:

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google place api 在 Android 中显示错误 的相关文章

随机推荐

  • 运行任意Python代码的Bokeh悬停工具

    我正在使用 Bokeh 尝试创建一个图形 当用户将其数据点 悬停 在其上时 将在悬停工具中显示另一个图形 显示有关该数据点的附加信息 即 在主图中 数据点是设定间隔内的时间序列 我希望悬停工具显示该间隔内的所有数据 The 用户指南 完整代
  • 从 SD 卡创建一个可绘制对象以设置为 Android 中的背景

    我正在尝试使用 SD 卡中的图像并将其设置为相对布局的背景 我尝试过在这里和其他地方找到的其他解决方案 但它们似乎对我不起作用 这是我的代码 我已经评论了我尝试过但不起作用的其他方法 唯一对我有用的是使用 setBackgroudnReso
  • 绑定到 VisualStateManager 中控件的属性

    我在 Stackoverflow 上搜索了这个问题 但我认为其他帖子没有涵盖这个问题 在我的自定义控件中 我使用视觉状态管理器 视觉状态管理器内部有一个动画 可以对元素的高度进行动画处理 当我尝试绑定到控件属性时 我在启动时收到以下错误 附
  • 上传文件不起作用 - 需要帮助

    我正在尝试使用 WebBrowser 控件上传文件 图像 似乎无法做到这一点 需要一些帮助 这是 HTML
  • 从 servlet 访问数据

    我有一个要求 mysql 数据库只能从本地主机访问 我必须实现一个 servlet 来访问数据库 从而允许该系统中的其他服务器访问数据 servlet 将充当代理 然而 该系统由一个远程服务器组成 该服务器下载大部分数据并执行如下语句 se
  • Bash 中的 RSS 日期到纪元

    寻找 bash 行以采用 RSS 日期格式 例如 Fri 13 Sep 2013 17 16 45 GMT 并将其转换为毫秒 我已经尝试过如下的事情 它们不会在几毫秒内产生 我运行的是 Mac OS X Snow Leopard 10 6
  • 在新存储库上推送原始主错误

    我刚刚开始使用 git 和 github 我按照他们的指示进行操作 但在最后一步遇到了错误 我正在检查当前不受源代码控制的现有目录 项目大约一周前 除此之外 我的用例应该是非常普通的 这是发生的事情 git push origin mast
  • 如何隐藏行索引

    我想将此 DataFrame 写入不带索引值的 xlsx 文件 我该怎么做 writer pd ExcelWriter r D pandas xlsx today datetime datetime today header pd Mult
  • 将 1 和 0 的字符串转换为二进制值

    我正在尝试将来自 stdin 的传入 1 和 0 字符串转换为各自的二进制值 其中诸如 11110111 之类的字符串将转换为 0xF7 这看起来很微不足道 但我不想重新发明轮子 所以我想知道 C C 标准库中是否有任何东西已经可以执行这样
  • 数组中给定数字的最小窗口

    最近看到这个问题 给定 2 个数组 第二个数组包含第一个数组的一些元素 返回第一个数组中包含第二个数组的所有元素的最小窗口 Eg 给定 A 1 3 5 2 3 1 和 B 1 3 2 Output 3 5 其中 3 和 5 是数组 A 中的
  • Javascript'this'值改变,但不明白为什么

    我是一个 Javascript 新手 我正在尝试了解 OLN 我遇到的是 当从同一对象上的另一个方法调用对象方法时 被调用方法中 this 的本地值正在改变 这是我的代码 var generator generateForLevelSkil
  • 使用 MPAndroidChart 库重叠饼图标签

    我正在使用菲尔杰MPAndroid图表图书馆 implementation com github PhilJay MPAndroidChart v3 1 0 And I implemented Pie Chart Pie Chart wit
  • 在Xamarin浏览器控件中访问html响应内容

    我有一个似乎不寻常的要求 我和我的同事无法在我们的 Xamarin 项目中实现 我们试图做的是动态处理浏览器导航到的任何页面的内容 而不是简单地处理从其访问的初始 URL 返回的内容 我见过以这种方式访问 返回内容的解决方案 Xamarin
  • 如何在 C# 中创建动态大小的数组或重新调整数组的大小?

    我需要知道如何在 C 中动态调整数组大小 在我下面编写的方法中 我需要能够返回一个仅包含用户输入的数字 最多 8 个数字 的数组 因此 如果用户决定只想输入 3 个数字 则数组应该只包含 3 个数字 而不是 8 个 现在我知道数组在实例化时
  • 在 Spring 测试中禁用 @EnableScheduling

    当我运行单元测试时 它会调用我的计划任务 我想防止这种行为 这是因为我有 EnableScheduling在我的主要应用程序配置上 如何在单元测试中禁用此功能 我遇到过这个问题 答案这建议设置配置文件 不知道我会怎么做 或者是否太过分了 我
  • MySQL 查询 - 使用 URL 名称识别数据,其中数据被组织成层次结构

    我有一个名为 content 的 mysql 表 它存储内容管理系统的内容数据 注意 所有内容都使用父 id 列组织成层次结构 id slug content type id parent 1 portfolio 5 0 2 about u
  • Java 同时淡入和淡出两个 JPanel

    我有一个 JPanel 列表 我想将其显示为 幻灯片 其中一个 JPanel 淡出 列表中的下一个 JPanel 淡入 这是我正在摆弄的代码 public float opacity 0f private Timer fadeTimer p
  • 在 Windows 上仅安装 Quicktime 库

    There s Quicktime SDK对于 Windows 但任何使用它的应用程序都需要在系统上安装 Quicktime 运行时库 SDK 本身只有标头和库存根 而不是实际的 DLL 如果我的应用程序使用 Quicktime 我想使用其
  • Jquery MVC 4 客户端验证不起作用

    我正在尝试在一个简单的 MVC 4 应用程序上使用 jQuery 验证插件 我在 MVC 3 中完成的操作没有任何问题 但我根本无法让它工作 我希望在以下情况下触发验证 1 我的控制失去焦点 2 提交表单 任何关于我错过的想法将不胜感激 L
  • Google place api 在 Android 中显示错误

    我在这里面临一个奇怪的问题 我想从我的 Android 应用程序查询 google 地点网络服务 为此 我总是收到错误 此服务需要 API 密钥 然而 当我尝试使用 Chrome 浏览器和服务器密钥查询它时 我得到了正确的响应 对于 and