使用适用于 android 的 google places api 网络服务搜索特定的附近地点
Posted
技术标签:
【中文标题】使用适用于 android 的 google places api 网络服务搜索特定的附近地点【英文标题】:Search specific nearby places using google places api web services for android 【发布时间】:2016-02-26 13:34:32 【问题描述】:我正在尝试使用 google places api 网络服务将地点搜索类型限制为医院,但无法实现。
Logcat
java.lang.NullPointerException 在 com.ediode.graphics3d.ClinicFragment.sbMethod(ClinicFragment.java:174) 在 com.ediode.graphics3d.ClinicFragment.onMapReady(ClinicFragment.java:95)
MainActivity
public class ClinicFragment extends AppCompatActivity implements
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,
LocationListener,
OnMapReadyCallback
private GoogleMap mGoogleMap;
SupportMapFragment mapFrag;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
LatLng latLng;
double mLatitude=0;
double mLongitude=0;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.clinic_fragment);
mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
@Override
public void onMapReady(GoogleMap googleMap)
mGoogleMap = googleMap;
mGoogleMap.setMyLocationEnabled(true);
buildGoogleApiClient();
mGoogleApiClient.connect();
StringBuilder sbValue = new StringBuilder(sbMethod());
PlacesTask placesTask = new PlacesTask();
placesTask.execute(sbValue.toString());
@Override
public void onPause()
super.onPause();
//Unregister for location callbacks:
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
@Override
public void onConnected(Bundle bundle) throws SecurityException
Toast.makeText(this,"Connected",Toast.LENGTH_SHORT).show();
// Get LocationManager object from System Service LOCATION_SERVICE
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// Create a criteria object to retrieve provider
Criteria criteria = new Criteria();
// Get the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
// Get Current Location
Location myLocation = locationManager.getLastKnownLocation(provider);
// Get latitude of the current location
double latitude = myLocation.getLatitude();
// Get longitude of the current location
double longitude = myLocation.getLongitude();
// Create a LatLng object for the current location
latLng = new LatLng(latitude, longitude);
//mGoogleMap.clear();
//latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
Marker m = mGoogleMap.addMarker(markerOptions);
m.showInfoWindow();
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));
Toast.makeText(this,"Touch the Pink Markers to View the Details of that Hospital",Toast.LENGTH_LONG).show();
@Override
public void onConnectionSuspended(int i)
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
@Override
public void onLocationChanged(Location location)
public StringBuilder sbMethod() throws SecurityException
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, true);
Location myLocation = locationManager.getLastKnownLocation(provider);
mLatitude=myLocation.getLatitude();
mLongitude=myLocation.getLongitude();
StringBuilder sb = new StringBuilder("https://maps.googleapis.com/maps/api/place/nearbysearch/json?");
sb.append("location=" + mLatitude + "," + mLongitude);
sb.append("&radius=20000");
sb.append("&types=" + "hospital|doctor");
sb.append("&sensor=true");
sb.append("&key=***********************");
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 = 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;
【问题讨论】:
可以添加 NullPointerException 的堆栈跟踪吗? 第 174 行的代码是什么? @DanielNugent 嘿,抱歉回复晚了,因为我正忙于其他工作。我已经编辑了我的问题。这就是我现在得到的。请问你能帮我解决这个问题吗? @NigamPatro 第 174 行 - mLatitude=myLocation.getLatitude(); 但是您还没有为条件设置任何值? 【参考方案1】:首先,您连接到 GooglePlayServices,但从未实际使用 GooglePlayServices 作为位置。
而不是这个:
Location myLocation = locationManager.getLastKnownLocation(provider);
你可能想这样做:
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
但是,这些方法总是有可能返回 null,因此请始终对上述方法的结果进行 null 检查。在调用 mLatitude=myLocation.getLatitude();
之前,您没有对此位置对象进行空值检查是导致 NullPointerException 的原因。
但是,我也建议不要调用 getLastLocation()
,因为它很容易返回 null。它也不会请求新位置,因此即使您返回位置,它也可能非常旧,并且无法反映设备的当前位置。最好注册一个监听器,即使你在收到第一个 onLocationChanged() 回调后取消注册。
看起来你基本上想结合this answer和this answer。
我只是基本做到了,还清理了一点代码。
这是整个类的代码:
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
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.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,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener
GoogleMap mGoogleMap;
SupportMapFragment mapFrag;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
Location mLastLocation;
Marker mCurrLocationMarker;
boolean firstRun = true;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFrag = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
@Override
public void onPause()
super.onPause();
//stop location updates when Activity is no longer active
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
@Override
public void onMapReady(GoogleMap googleMap)
mGoogleMap=googleMap;
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
//Initialize Google Play Services
buildGoogleApiClient();
mGoogleApiClient.connect();
public StringBuilder sbMethod(Location currentLocation)
//current location
double mLatitude = currentLocation.getLatitude();
double mLongitude = currentLocation.getLongitude();
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", "<><>api: " + sb.toString());
return sb;
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
@Override
public void onConnected(Bundle bundle)
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
@Override
public void onLocationChanged(Location location)
mLastLocation = location;
if (mCurrLocationMarker != null)
mCurrLocationMarker.remove();
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mGoogleMap.addMarker(markerOptions);
//move map camera
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));
//query places with current location
StringBuilder sbValue = new StringBuilder(sbMethod(location));
PlacesTask placesTask = new PlacesTask();
placesTask.execute(sbValue.toString());
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
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)
Log.d("result", "<><> result: " + 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;
if (!firstRun)
mGoogleMap.clear();
firstRun = false;
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;
结果:
【讨论】:
仍然报错。 java.lang.NullPointerException at com.ediode.graphics3d.ClinicFragment$ParserTask.onPostExecute(ClinicFragment.java:268) at com.ediode.graphics3d.ClinicFragment$ParserTask.onPostExecute(ClinicFragment.java:242) @User0706 您可以添加完整的堆栈跟踪,并更新问题中的代码吗?第 268 行是什么? 已更新。看看吧 @User0706 查看此行输出的日志:Log.d("Map", "api url: " + sb.toString());
,然后在浏览器中尝试该 url。
我现在可以看到我当前的位置,但附近的医院不可见以上是关于使用适用于 android 的 google places api 网络服务搜索特定的附近地点的主要内容,如果未能解决你的问题,请参考以下文章
为啥使用 KML 数据检索适用于 Android 的 Google 路线不再有效? [复制]
获取适用于 Android 的 Google Places API 密钥
适用于 Android 的 Google 登录 - 发布与调试
如何使用适用于 Android V2 的 Google Maps 处理地图移动端?