无法从android中的谷歌地图获取地点数据

Posted

技术标签:

【中文标题】无法从android中的谷歌地图获取地点数据【英文标题】:Can not get places data from google map in android 【发布时间】:2021-10-08 15:50:02 【问题描述】:

我想显示附近医院的列表,但我无法从 Google 地图中获取数据。 (但是当我使用用户的 API 密钥学习在 android 中显示地图时,我能够获取数据。)

我已经做过的事情:

    从谷歌云控制台启用 Map API 和 Place API 设置结算帐号

代码 XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:background="@color/white"
    android:orientation="vertical"
    android:weightSum="10">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_
        android:layout_
        android:background="@color/colorPrimaryDark"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/imageDrawer"
            android:layout_
            android:layout_
            android:contentDescription="@string/app_name"
            android:gravity="center_vertical"
            android:src="@drawable/back_arrows" />

        <TextView
            android:id="@+id/textTitle"
            android:layout_
            android:layout_
            android:layout_marginStart="@dimen/_24sdp"
            android:background="@drawable/title_stroke"
            android:fontFamily="@font/ubuntu_bold"
            android:gravity="center_vertical"
            android:paddingStart="@dimen/_8sdp"
            android:paddingTop="@dimen/_2sdp"
            android:paddingEnd="@dimen/_8sdp"
            android:paddingBottom="@dimen/_2sdp"
            android:text="@string/nearby"
            android:textColor="@color/white"
            android:textSize="@dimen/_16ssp" />
    </androidx.appcompat.widget.Toolbar>

    <fragment
        android:id="@+id/googleMap"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:layout_
        android:layout_
        android:layout_weight="5"
        tools:ignore="FragmentTagUsage" />

    <ListView
        android:id="@+id/centersListView"
        android:layout_
        android:layout_
        android:layout_weight="5" />

</LinearLayout>

Java 类

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.ListView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentActivity;

import com.aaienafit.R;
import com.aaienafit.databinding.ActivityDoctorBinding;
import com.aaienafit.utils.ProgressDialog;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.maps.CameraUpdateFactory;
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.MarkerOptions;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class DoctorActivity extends FragmentActivity implements OnMapReadyCallback 

    ActivityDoctorBinding binding;

    StringBuffer stringBuffer;
    ListView centersListView;
    double latitude, longitude;
    LocationManager locationManager;
    Location location;
    private GoogleMap mMap;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        binding = ActivityDoctorBinding.inflate(LayoutInflater.from(this));
        setContentView(binding.getRoot());

        stringBuffer = new StringBuffer();
        centersListView = findViewById(R.id.centersListView);

        centersListView.setOnItemClickListener((adapterView, view, i, l) -> new AlertDialog.Builder(DoctorActivity.this).setCancelable(true).setTitle(LocationController.detailArrayList.get(i).getHospitalName()).setMessage(LocationController.detailArrayList.get(i).getAddress()).setIcon(R.drawable.marker).show());

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.googleMap);
        if (mapFragment != null) 
            mapFragment.getMapAsync(this);

        
        getList();


    


    @Override
    public void onMapReady(@NonNull GoogleMap googleMap) 
        mMap = googleMap;

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) 
            mMap.setMyLocationEnabled(true);
            setUpCameraAndMarkers();
            LatLng latLng = new LatLng(latitude, longitude);
            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11f));
            Objects.requireNonNull(mMap.addMarker(new MarkerOptions().position(latLng))).setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));

        

    

    public void updateLoc() 
        locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) 
            throw new IllegalArgumentException("No GPS");
         else if (!isGooglePlayServicesAvailable(this)) 
            throw new IllegalArgumentException("No Google Play Services Available");
         else getLocation();

    

    public boolean isGooglePlayServicesAvailable(Context context) 
        GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context);
        return resultCode == ConnectionResult.SUCCESS;
    

    void getLocation() 
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) 
            try 
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                if (location != null) 
                    Log.d("latitude=>", location.getLatitude() + ", longitude=> " + location.getLongitude());
                    latitude = location.getLatitude();
                    longitude = location.getLongitude();

                

             catch (Exception e) 
                Log.d("LOCATION_UPDATE", "getLocation: ");
            


        


    

    protected void fillList() 
        ArrayList<String> placeName = new ArrayList<>();
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) 
            placeName.add(LocationController.detailArrayList.get(i).getHospitalName());
        


        ArrayList<String> address = new ArrayList<>();
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) 
            address.add(LocationController.detailArrayList.get(i).getAddress());
        

        PlacesListAdapter placesListAdapter = new PlacesListAdapter(this, placeName, address);
        centersListView.setAdapter(placesListAdapter);
    

    void loadLocation() 
        try 
            RetrieveFeedTask();
            new Thread(() -> 
                while (stringBuffer.length() == 0) Log.d("Message", "buffer reading");
                LocationController.manipulateData(stringBuffer);
            ).start();
         catch (Exception e) 
            e.printStackTrace();
        
    

    void RetrieveFeedTask() 

        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> 

            try 
                String string =
                        "https://maps.googleapis.com/maps/api/place/search/json?rankby=distance&keyword=hospital&location=" +
                                latitude +
                                "," +
                                longitude +
                                "&key=" + getString(R.string.google_api_key) + "&libraries=places";
               

                URL url = new URL(string);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = connection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuffer buffer = new StringBuffer();

                String n;
                while ((n = bufferedReader.readLine()) != null) 
                    buffer.append(n);
                

                stringBuffer = buffer;
             catch (Exception e) 
                Toast.makeText(DoctorActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            

        );
    

    void getList() 
        try 
            updateLoc();
            LocationController.loading = true;
            loadLocation();
            while (LocationController.loading) 
                Log.d("GeometryResponse", "Waiting for response");
            
            fillList();
         catch (IllegalArgumentException e) 
            Toast.makeText(DoctorActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
        
        if (ProgressDialog.isProgressShowing()) 
            ProgressDialog.dismissProgressDialog();
        
    

    void setUpCameraAndMarkers() 
        LatLng latLng;
        for (int i = 0; i < LocationController.detailArrayList.size(); i++) 
            latLng = new LatLng(LocationController.detailArrayList.get(i).getGeometry()[0], LocationController.detailArrayList.get(i).getGeometry()[1]);
            mMap.addMarker(new MarkerOptions().position(latLng).title(LocationController.detailArrayList.get(i).getHospitalName()));
            mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        


    



PlacesListAdapter 类

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.aaienafit.R;

import java.util.ArrayList;

public class PlacesListAdapter extends BaseAdapter 


    private final Context context;
    private final ArrayList<String> placeName;
    private final ArrayList<String> openNowText;


    public PlacesListAdapter(Context context, ArrayList<String> placeName, ArrayList<String> openNowText) 
        this.context = context;
        this.placeName = placeName;
        this.openNowText = openNowText;
    


    @Override
    public int getCount() 
        return placeName.size();
    

    @Override
    public Object getItem(int i) 
        return placeName.get(i);
    

    @Override
    public long getItemId(int i) 
        return 3232;
    

    @SuppressLint("SetTextI18n")
    @Override
    public View getView(int i, View view, ViewGroup viewGroup) 

        if (view == null) view = View.inflate(context, R.layout.doctor_list_item, null);

        TextView placeTextView = view.findViewById(R.id.textDoctorName);
        TextView address = view.findViewById(R.id.textAddress);

        placeTextView.setText(placeName.get(i));
        address.setText(openNowText.get(i));

        return view;
    

HospitalModel 类

import androidx.annotation.NonNull;

import java.util.Arrays;

public class HospitalModel 

    private String hospitalName;
    private String rating;
    private String openingHours;
    private String address;
    private double[] geometry;

    public String getHospitalName() 
        return hospitalName;
    

    public void setHospitalName(String hospitalName) 
        this.hospitalName = hospitalName;
    

    public String getRating() 
        return rating;
    

    public void setRating(String rating) 
        this.rating = rating;
    

    public String getOpeningHours() 
        return openingHours;
    

    public void setOpeningHours(String openingHours) 
        this.openingHours = openingHours;
    

    public String getAddress() 
        return address;
    

    public void setAddress(String address) 
        this.address = address;
    

    public double[] getGeometry() 
        return geometry;
    

    public void setGeometry(double[] geometry) 
        this.geometry = geometry;
    

    @NonNull
    @Override
    public String toString() 
        return "NearbyHospitalsDetail" +
                ", hospitalName='" + hospitalName + '\'' +
                ", rating=" + rating +
                ", openingHours='" + openingHours + '\'' +
                ", address='" + address + '\'' +
                ", geometry=" + Arrays.toString(geometry) +
                '';
    

LocationController 类

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;


public class LocationController 

    public static boolean loading;
    public static ArrayList<HospitalModel> detailArrayList = new ArrayList<>();

    public static void manipulateData(StringBuffer buffer) 
        loading = true;
        try 
            detailArrayList.clear();
            JSONObject object = new JSONObject(buffer.toString());
            JSONArray array = object.getJSONArray("results");
            for (int i = 0; i < array.length(); i++) 
                try 
                    JSONObject jsonObject = array.getJSONObject(i);
                    HospitalModel hospitalsDetail = new HospitalModel();

                    jsonObject.getString("name");
                    hospitalsDetail.setHospitalName(jsonObject.getString("name"));

                    try 
                        hospitalsDetail.setRating(String.valueOf(jsonObject.getDouble("rating")));
                     catch (Exception e) 
                        hospitalsDetail.setRating("Not Available");
                    
                    try 
                        if (jsonObject.getJSONObject("opening_hours").getBoolean("open_now"))
                            hospitalsDetail.setOpeningHours("Opened");
                        else hospitalsDetail.setOpeningHours("closed");
                     catch (Exception e) 
                        hospitalsDetail.setOpeningHours("Not Available");
                    

                    hospitalsDetail.setAddress(jsonObject.getString("vicinity"));
                    hospitalsDetail.setGeometry(new double[]jsonObject.getJSONObject("geometry").getJSONObject("location").getDouble("lat"),
                            jsonObject.getJSONObject("geometry").getJSONObject("location").getDouble("lng"));

                    detailArrayList.add(hospitalsDetail);
                 catch (Exception e) 
                    e.printStackTrace();
                
            

         catch (Exception e) 
            e.printStackTrace();
        

        loading = false;
        Log.d("Array Loaded with size ", "Size of " + detailArrayList.size());
    

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example">
    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the "MyLocation" functionality.
    -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission
        android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <uses-permission android:name="android.permission.CAMERA" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="true" />

    <queries>
        <intent>
            <action android:name="com.google.android.youtube.api.service.START" />
        </intent>
    </queries>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AaienaFit"
        android:usesCleartextTraffic="true"
        tools:ignore="AllowBackup"
        tools:targetApi="m">
        <activity
            android:name=".activities.youtubePlayer.YoutubePlayerActivity"
            android:configChanges="orientation|screenSize"
            android:noHistory="true" />

        <uses-library
            android:name="org.apache.http.legacy"
            android:required="false" />

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_api_key" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name=".activities.doctor.DoctorActivity" />
        <activity
            android:name=".utils.SplashScreen"
            android:noHistory="true"
            android:theme="@style/Splash"
            tools:ignore="IntentFilterExportedReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".activities.authentication.AuthenticationActivity" />
        <activity android:name=".activities.main.MainActivity" />

        <receiver
            android:name=".broadcasts.NotificationBroadcast"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="button_click" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

【问题讨论】:

【参考方案1】:

尝试 API 端点maps/api/place/nearbysearch

https://maps.googleapis.com/maps/api/place/nearbysearch/output?parameters

根据“Java 类”文件中的示例代码,URL 构造如下所示

"https://maps.googleapis.com/maps/api/place/nearbysearch/json?" +
    "rankby=distance&" +
    "keyword=hospital&" + 
    "location=" + latitude + "," + longitude + "&" +
    "key=" + getString(R.string.google_api_key);

快速旁注

我强烈建议您查看 *** 的指南,以便为您的问题创建 Minimal, Reproducible Example。在您在原始答案中发布的六个源文件和数百行代码中,只有几十行与从 Google 的 Maps API 获取附近医院数据的特定任务相关。将您的问题和代码示例集中在手头的特定问题上,这将使志愿者帮助回答您的问题变得容易几个数量级,甚至可以帮助您自己找到答案。

【讨论】:

首先感谢您的建议,我以后记住了。但答案不起作用。【参考方案2】:

试试这个:

在您的应用之外,在浏览器(Firefox/chrome/safari 等)上测试端点,如果您获得附近的医院列表,现在转到您的应用。

在应用程序上,一旦您在浏览器上测试了端点,现在请确保您的参数Required Parameters(需要传递给端点的参数)确实存在。您可以通过在进行 api 调用/使用 api 的位置放置断点来实现此目的,或者在目标参数上放置断点。

如果您能够获取值,请使用this 方法来使用 google maps api,或使用改造。

如果没有,请联系我们。

【讨论】:

以上是关于无法从android中的谷歌地图获取地点数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ionic 2 中的谷歌地图获取纬度和经度?

颤动的谷歌地图无法显示来自firebase的标记

从 php 中的谷歌地图获取国家名称

在android中的谷歌地图上绘制点

如何从angularJS中的谷歌地图标记获取动态位置

Flutter 中的谷歌地图导航