使用谷歌Places API的Web服务为Android特定搜索附近的地方 [英] Search specific nearby places using google places api web services for android
问题描述
我想使用谷歌Places API的Web服务来限制地方搜索类型医院,但无法实现它。
的logcat
显示java.lang.NullPointerException
在com.ediode.graphics3d.ClinicFragment.sbMethod(ClinicFragment.java:174)
在com.ediode.graphics3d.ClinicFragment.onMa pready(ClinicFragment.java:95)
块引用>MainActivity
公共类ClinicFragment扩展AppCompatActivity工具
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,
LocationListener的,
OnMa preadyCallback
{
私人GoogleMap的mGoogleMap;
SupportMapFragment mapFrag;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
经纬度的latLng;
双mLatitude = 0;
双mLongitude = 0; @覆盖
保护无效的onCreate(捆绑savedInstanceState)
{
super.onCreate(savedInstanceState); 的setContentView(R.layout.clinic_fragment); mapFrag =(SupportMapFragment)getSupportFragmentManager()findFragmentById(R.id.map)。
mapFrag.getMapAsync(本);
} @覆盖
公共无效onMa pready(GoogleMap的GoogleMap的)
{ mGoogleMap = GoogleMap的;
mGoogleMap.setMyLocationEnabled(真);
buildGoogleApiClient();
mGoogleApiClient.connect();
StringBuilder的sbValue =新的StringBuilder(sbMethod());
PlacesTask placesTask =新PlacesTask();
placesTask.execute(sbValue.toString());
} @覆盖
公共无效的onPause()
{
super.onPause();
//取消注册地点回调:
如果(mGoogleApiClient!= NULL)
{
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,这一点);
}
} 保护同步无效buildGoogleApiClient()
{
mGoogleApiClient =新GoogleApiClient.Builder(本)
.addConnectionCallbacks(本)
.addOnConnectionFailedListener(本)
.addApi(LocationServices.API)
。建立();
} @覆盖
公共无效onConnected(包捆)抛出SecurityException异常
{
Toast.makeText(这一点,连接,Toast.LENGTH_SHORT).show();
//从系统服务LOCATION_SERVICE获取的LocationManager对象
的LocationManager的LocationManager =(的LocationManager)getSystemService(Context.LOCATION_SERVICE);
//创建一个标准的对象来检索提供商
标准标准=新标准();
//获取最佳供应商的名称
字符串提供商= locationManager.getBestProvider(标准,真正的);
//获取当前位置
位置myLocation = locationManager.getLastKnownLocation(供应商);
//获取当前位置的纬度
双纬度= myLocation.getLatitude();
//获取当前位置的经度
双经度= myLocation.getLongitude();
//创建一个经纬度对象的当前位置
的latLng =新的经纬度(纬度,经度); //mGoogleMap.clear();
//的latLng =新经纬度(mLastLocation.getLatitude(),mLastLocation.getLongitude());
的MarkerOptions的MarkerOptions =新的MarkerOptions();
markerOptions.position(的latLng);
markerOptions.title(当前位置);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
标记M = mGoogleMap.addMarker(的MarkerOptions);
m.showInfoWindow();
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(的latLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11));
Toast.makeText(这一点,触摸红色标记,以查看该医院的详细信息,Toast.LENGTH_LONG).show();
} @覆盖
公共无效onConnectionSuspended(int i)以{
Toast.makeText(这一点,onConnectionSuspended,Toast.LENGTH_SHORT).show();
} @覆盖
公共无效onConnectionFailed(ConnectionResult connectionResult){
Toast.makeText(这一点,onConnectionFailed,Toast.LENGTH_SHORT).show();
} @覆盖
公共无效onLocationChanged(地点){ }
公众的StringBuilder sbMethod()抛出SecurityException异常
{
的LocationManager的LocationManager =(的LocationManager)getSystemService(Context.LOCATION_SERVICE);
标准标准=新标准();
字符串提供商= locationManager.getBestProvider(标准,真正的);
位置myLocation = locationManager.getLastKnownLocation(供应商);
mLatitude = myLocation.getLatitude();
mLongitude = myLocation.getLongitude(); StringBuilder的SB =新的StringBuilder(https://maps.googleapis.com/maps/api/place/nearbysearch/json?);
sb.append(位置=+ mLatitude +,+ mLongitude);
sb.append(与&半径= 20000);
sb.append(与&类型=+号医院|医生);
sb.append(与&传感器=真正的); sb.append(与&关键= ***********************); Log.d(地图,URL:+ sb.toString()); 返回SB;
} 私有类PlacesTask扩展的AsyncTask<字符串,整数,字符串>
{ 字符串数据= NULL;这个对象//通过调用执行()方法
@覆盖
保护字符串doInBackground(字符串... URL){
尝试{
数据= downloadUrl(URL [0]);
}赶上(例外五){
Log.d(后台任务,e.toString());
}
返回的数据;
}// doInBackground完全执行(后执行)方法
@覆盖
保护无效onPostExecute(字符串结果){
ParserTask parserTask =新ParserTask(); //开始解析JSON格式的谷歌的地方
//调用的doInBackground()之类ParserTask的方法
parserTask.execute(结果);
}
}
私人字符串downloadUrl(字符串strUrl)抛出IOException异常
{
字符串数据=;
InputStream中的IStream = NULL;
HttpURLConnection类的URLConnection = NULL;
尝试{
网址URL =新的URL(strUrl); //创建一个HTTP连接使用网址进行沟通
URLConnection的=(HttpURLConnection类)url.openConnection(); //连接给url
urlConnection.connect(); // URL从读取数据
的IStream = urlConnection.getInputStream(); BR的BufferedReader =新的BufferedReader(新的InputStreamReader(的IStream)); StringBuffer的SB =新的StringBuffer(); 串线=;
而((行= br.readLine())!= NULL){
sb.append(线);
} 数据= sb.toString(); br.close(); }赶上(例外五){
Log.d(异常,e.toString());
} {最后
iStream.close();
urlConnection.disconnect();
}
返回的数据;
}私有类ParserTask扩展的AsyncTask<字符串,整数,列表<&HashMap的LT;字符串,字符串>>> {的JSONObject jObject;这个对象//通过调用执行()方法
@覆盖
保护列表与LT; HashMap的<字符串,字符串>> doInBackground(字符串... jsonData){ 清单<&HashMap的LT;字符串,字符串>>地方= NULL;
Place_JSON placeJson =新Place_JSON(); 尝试{
jObject =新的JSONObject(jsonData [0]); 地方= placeJson.parse(jObject); }赶上(例外五){
Log.d(异常,e.toString());
}
回到地方;
}// doInBackground完全执行(后执行)方法
@覆盖
保护无效onPostExecute(列表<&HashMap的LT;字符串,字符串>>名单){ Log.d(地图,列表的大小:+则为list.size());
//清除所有现有的标记;
//mGoogleMap.clear(); 的for(int i = 0; I<则为list.size();我++){ //创建一个标志
的MarkerOptions的MarkerOptions =新的MarkerOptions(); //充分利用地方名单的地方
HashMap的<字符串,字符串> hmPlace = list.get(ⅰ);
//获取地方纬度
双纬度= Double.parseDouble(hmPlace.get(纬度)); //获取地方的经度
双LNG = Double.parseDouble(hmPlace.get(LNG)); //获取名称
字符串名称= hmPlace.get(PLACE_NAME); Log.d(地图,地点+姓名); //获取附近
附近的String = hmPlace.get(附近); 的latLng =新的经纬度(纬度,经度); //设置对标记的位置
markerOptions.position(的latLng); markerOptions.title(名称+:+附近); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); //放置一个标记上触摸的位置
标记M = mGoogleMap.addMarker(的MarkerOptions);
}
}
}
公共类Place_JSON {/ **
*接收一个JSONObject并返回一个列表
* /
公开名单<&HashMap的LT;字符串,字符串>>解析(JSONObject的jObject){ JSONArray jPlaces = NULL;
尝试{
/ **获取所有元素的'地方'数组中* /
jPlaces = jObject.getJSONArray(结果);
}赶上(JSONException E){
e.printStackTrace();
}
/ **调用getPlaces和JSON对象的数组
*每个JSON对象重新present的地方
* /
返回getPlaces(jPlaces);
}私人列表<&HashMap的LT;字符串,字符串>> getPlaces(JSONArray jPlaces){
INT placesCount = jPlaces.length();
清单<&HashMap的LT;字符串,字符串>> placesList =新的ArrayList<&HashMap的LT;字符串,字符串>>();
HashMap的<字符串,字符串>地方= NULL; / **以每一个地方,解析并添加到列表对象* /
的for(int i = 0; I< placesCount;我++){
尝试{
/ **调用getPlace与地方JSON对象解析地方* /
地方= getPlace((JSONObject的)jPlaces.get(一));
placesList.add(地方);
}赶上(JSONException E){
e.printStackTrace();
}
}
返回placesList;
}/ **
*解析广场JSON对象
* /
私人的HashMap<字符串,字符串> getPlace(JSONObject的jPlace)
{ HashMap的<字符串,字符串>地方=新的HashMap<字符串,字符串>();
字符串地名=-NA-;
附近的String =-NA-;
串纬度=;
字符串的经度=;
String引用=; 尝试{
//提取地名,如果有的话
如果(!jPlace.isNull(名字)){
地名= jPlace.getString(名称);
} //提取广场气象台,如果可用
如果(!jPlace.isNull(附近)){
附近= jPlace.getString(附近);
} 纬度= jPlace.getJSONObject(几何)getJSONObject(位置)的getString(纬度)。;
经度= jPlace.getJSONObject(几何)getJSONObject(位置)的getString(LNG)。;
基准= jPlace.getString(参考); place.put(PLACE_NAME,地名);
place.put(附近,附近);
place.put(纬度,纬度);
place.put(LNG,经度);
place.put(参考,参考); }赶上(JSONException E){
e.printStackTrace();
}
回到地方;
}
}
解决方案首先,要连接到GooglePlayServices,但从未实际使用GooglePlayServices的位置。
而不是这样的:
位置myLocation = locationManager.getLastKnownLocation(供应商);
您可能想做到这一点:
位置mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);然而,这些方法总是有返回null的机会,所以总是在上述方法的结果的空检查。你缺乏这个位置对象的空支票之前调用
mLatitude = myLocation.getLatitude();
是什么导致你的NullPointerException不过,我也建议不要叫
getLastLocation()
可言,因而具有较高的倾向返回null。它也不会要求一个新的位置,因此,即使你得到一个位置返回,也可能是很老了,不能反映设备的当前位置。这是更好地注册一个监听器,你先去onLocationChanged()回调后,即使你只是注销。我基本上只是这样做,也清理了code位。
下面是整个类code:
进口android.location.Location;
进口android.os.AsyncTask;
进口android.os.Bundle;
进口android.support.v7.app.AppCompatActivity;
进口android.util.Log;
进口com.google.android.gms.common.ConnectionResult;
进口com.google.android.gms.common.api.GoogleApiClient;
进口com.google.android.gms.location.LocationListener;
进口com.google.android.gms.location.LocationRequest;
进口com.google.android.gms.location.LocationServices;
进口com.google.android.gms.maps.CameraUpdateFactory;
进口com.google.android.gms.maps.GoogleMap;
进口com.google.android.gms.maps.OnMa preadyCallback;
进口com.google.android.gms.maps.SupportMapFragment;
进口com.google.android.gms.maps.model.BitmapDescriptorFactory;
进口com.google.android.gms.maps.model.LatLng;
进口com.google.android.gms.maps.model.Marker;
进口com.google.android.gms.maps.model.MarkerOptions;
进口org.json.JSONArray;
进口org.json.JSONException;
进口org.json.JSONObject;
进口java.io.BufferedReader中;
进口java.io.IOException异常;
进口的java.io.InputStream;
进口java.io.InputStreamReader中;
进口java.net.HttpURLConnection中;
进口的java.net.URL;
进口的java.util.ArrayList;
进口的java.util.HashMap;
进口的java.util.List;公共类MapsActivity2扩展AppCompatActivity
实现OnMa preadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener的{ GoogleMap的mGoogleMap;
SupportMapFragment mapFrag;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
位置mLastLocation;
标记mCurrLocationMarker;
布尔firstRun =真; @覆盖
保护无效的onCreate(捆绑savedInstanceState)
{
super.onCreate(savedInstanceState);
的setContentView(R.layout.activity_main); mapFrag =(SupportMapFragment)getSupportFragmentManager()findFragmentById(R.id.map)。
mapFrag.getMapAsync(本);
} @覆盖
公共无效的onPause(){
super.onPause(); //停止位置更新时的活动不再有效
如果(mGoogleApiClient!= NULL){
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,这一点);
}
} @覆盖
公共无效onMa pready(GoogleMap的GoogleMap的)
{
mGoogleMap = GoogleMap的;
mGoogleMap.setMyLocationEnabled(真);
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); //初始化谷歌播放服务
buildGoogleApiClient();
mGoogleApiClient.connect();
} 公众的StringBuilder sbMethod(位置currentLocation){
//当前位置
双mLatitude = currentLocation.getLatitude();
双mLongitude = currentLocation.getLongitude(); StringBuilder的SB =新的StringBuilder(https://maps.googleapis.com/maps/api/place/nearbysearch/json?);
sb.append(位置=+ mLatitude +,+ mLongitude);
sb.append(与&半径= 5000);
sb.append(与&类型=+餐厅);
sb.append(与&传感器=真正的); sb.append(与&关键= AIza ********); Log.d(地图,<><> API:+ sb.toString()); 返回SB;
} 保护同步无效buildGoogleApiClient(){
mGoogleApiClient =新GoogleApiClient.Builder(本)
.addConnectionCallbacks(本)
.addOnConnectionFailedListener(本)
.addApi(LocationServices.API)
。建立();
} @覆盖
公共无效onConnected(束束){
mLocationRequest =新LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,这一点);
} @覆盖
公共无效onConnectionSuspended(int i)以{} @覆盖
公共无效onConnectionFailed(ConnectionResult connectionResult){} @覆盖
公共无效onLocationChanged(地点)
{
mLastLocation =位置;
如果(mCurrLocationMarker!= NULL){
mCurrLocationMarker.remove();
} //将当前的位置标记
经纬度的latLng =新的经纬度(location.getLatitude(),location.getLongitude());
的MarkerOptions的MarkerOptions =新的MarkerOptions();
markerOptions.position(的latLng);
markerOptions.title(当前位置);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA));
mCurrLocationMarker = mGoogleMap.addMarker(的MarkerOptions); //移动地图相机
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(的latLng));
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(11)); //查询与地方的当前位置
StringBuilder的sbValue =新的StringBuilder(sbMethod(位置));
PlacesTask placesTask =新PlacesTask();
placesTask.execute(sbValue.toString()); 如果(mGoogleApiClient!= NULL){
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,这一点);
}
} 私有类PlacesTask扩展的AsyncTask<字符串,整数,字符串>
{ 字符串数据= NULL; 这个对象//通过调用执行()方法
@覆盖
保护字符串doInBackground(字符串... URL){
尝试{
数据= downloadUrl(URL [0]);
}赶上(例外五){
Log.d(后台任务,e.toString());
}
返回的数据;
} // doInBackground完全执行(后执行)方法
@覆盖
保护无效onPostExecute(字符串结果){
Log.d(结果,&所述;>&下;>结果:+导致);
ParserTask parserTask =新ParserTask(); //开始解析JSON格式的谷歌的地方
//调用的doInBackground()之类ParserTask的方法
parserTask.execute(结果);
}
} 私人字符串downloadUrl(字符串strUrl)抛出IOException异常
{
字符串数据=;
InputStream中的IStream = NULL;
HttpURLConnection类的URLConnection = NULL;
尝试{
网址URL =新的URL(strUrl); //创建一个HTTP连接使用网址进行沟通
URLConnection的=(HttpURLConnection类)url.openConnection(); //连接给url
urlConnection.connect(); // URL从读取数据
的IStream = urlConnection.getInputStream(); BR的BufferedReader =新的BufferedReader(新的InputStreamReader(的IStream)); StringBuffer的SB =新的StringBuffer(); 串线=;
而((行= br.readLine())!= NULL){
sb.append(线);
} 数据= sb.toString(); br.close(); }赶上(例外五){
Log.d(异常,e.toString());
} {最后
iStream.close();
urlConnection.disconnect();
}
返回的数据;
} 私有类ParserTask扩展的AsyncTask<字符串,整数,列表<&HashMap的LT;字符串,字符串>>> { 的JSONObject jObject; 这个对象//通过调用执行()方法
@覆盖
保护列表与LT; HashMap的<字符串,字符串>> doInBackground(字符串... jsonData){ 清单<&HashMap的LT;字符串,字符串>>地方= NULL;
Place_JSON placeJson =新Place_JSON(); 尝试{
jObject =新的JSONObject(jsonData [0]); 地方= placeJson.parse(jObject); }赶上(例外五){
Log.d(异常,e.toString());
}
回到地方;
} // doInBackground完全执行(后执行)方法
@覆盖
保护无效onPostExecute(列表<&HashMap的LT;字符串,字符串>>名单){ Log.d(地图,列表的大小:+则为list.size());
//清除所有现有的标记;
如果(!firstRun){ mGoogleMap.clear();
}
firstRun = FALSE; 的for(int i = 0; I<则为list.size();我++){ //创建一个标志
的MarkerOptions的MarkerOptions =新的MarkerOptions(); //充分利用地方名单的地方
HashMap的<字符串,字符串> hmPlace = list.get(ⅰ);
//获取地方纬度
双纬度= Double.parseDouble(hmPlace.get(纬度)); //获取地方的经度
双LNG = Double.parseDouble(hmPlace.get(LNG)); //获取名称
字符串名称= hmPlace.get(PLACE_NAME); Log.d(地图,地点+姓名); //获取附近
附近的String = hmPlace.get(附近); 经纬度的latLng =新的经纬度(纬度,经度); //设置对标记的位置
markerOptions.position(的latLng); markerOptions.title(名称+:+附近); markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); //放置一个标记上触摸的位置
标记M = mGoogleMap.addMarker(的MarkerOptions); }
}
}
公共类Place_JSON { / **
*接收一个JSONObject并返回一个列表
* /
公开名单<&HashMap的LT;字符串,字符串>>解析(JSONObject的jObject){ JSONArray jPlaces = NULL;
尝试{
/ **获取所有元素的'地方'数组中* /
jPlaces = jObject.getJSONArray(结果);
}赶上(JSONException E){
e.printStackTrace();
}
/ **调用getPlaces和JSON对象的数组
*每个JSON对象重新present的地方
* /
返回getPlaces(jPlaces);
} 私人列表<&HashMap的LT;字符串,字符串>> getPlaces(JSONArray jPlaces){
INT placesCount = jPlaces.length();
清单<&HashMap的LT;字符串,字符串>> placesList =新的ArrayList<&HashMap的LT;字符串,字符串>>();
HashMap的<字符串,字符串>地方= NULL; / **以每一个地方,解析并添加到列表对象* /
的for(int i = 0; I< placesCount;我++){
尝试{
/ **调用getPlace与地方JSON对象解析地方* /
地方= getPlace((JSONObject的)jPlaces.get(一));
placesList.add(地方);
}赶上(JSONException E){
e.printStackTrace();
}
}
返回placesList;
} / **
*解析广场JSON对象
* /
私人的HashMap<字符串,字符串> getPlace(JSONObject的jPlace)
{ HashMap的<字符串,字符串>地方=新的HashMap<字符串,字符串>();
字符串地名=-NA-;
附近的String =-NA-;
串纬度=;
字符串的经度=;
String引用=; 尝试{
//提取地名,如果有的话
如果(!jPlace.isNull(名字)){
地名= jPlace.getString(名称);
} //提取广场气象台,如果可用
如果(!jPlace.isNull(附近)){
附近= jPlace.getString(附近);
} 纬度= jPlace.getJSONObject(几何)getJSONObject(位置)的getString(纬度)。;
经度= jPlace.getJSONObject(几何)getJSONObject(位置)的getString(LNG)。;
基准= jPlace.getString(参考); place.put(PLACE_NAME,地名);
place.put(附近,附近);
place.put(纬度,纬度);
place.put(LNG,经度);
place.put(参考,参考); }赶上(JSONException E){
e.printStackTrace();
}
回到地方;
}
}}结果:
I am trying to limit the place search type to hospital using google places api web services but unable to achieve it.
Logcat
java.lang.NullPointerException at com.ediode.graphics3d.ClinicFragment.sbMethod(ClinicFragment.java:174) at 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; } }
解决方案First of all, you're connecting to GooglePlayServices, but never actually using GooglePlayServices for the location.
Instead of this:
Location myLocation = locationManager.getLastKnownLocation(provider);
You probably wanted to do this:
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation( mGoogleApiClient);
However, these methods always have a chance of returning null, so always do a null check on the result of the above methods. Your lack of a null check on this location object before calling
mLatitude=myLocation.getLatitude();
is what was causing your NullPointerException.However, I would also advise against calling
getLastLocation()
at all, which has a high tendency to return null. It also does not request a new location, so even if you get a location returned, it could be very old, and not reflect the current location of the device. It's better to register a listener, even if you just unregister after you get the first onLocationChanged() callback.It looks like you basically want to combine this answer and this answer.
I just basically did that, and also cleaned up the code a bit.
Here's the entire class code:
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; } } }
Result:
这篇关于使用谷歌Places API的Web服务为Android特定搜索附近的地方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!