我想使用谷歌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: