无法从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中的谷歌地图获取地点数据的主要内容,如果未能解决你的问题,请参考以下文章