我正在开发一款Android应用程序,该应用程序根据GPS位置查询数据库以检索特定距离内的最近位置(在其上设置标记)。
我遵循了本教程http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/,因此我尝试使用HttpRequest从PHP脚本中检索JSON。 我在调用getJSONArray方法时遇到NullPointerException。
这里是logcat
05-27 22:22:56.964: E/AndroidRuntime(26452): FATAL EXCEPTION: main
05-27 22:22:56.964: E/AndroidRuntime(26452): java.lang.NullPointerException
05-27 22:22:56.964: E/AndroidRuntime(26452): at com.example.mypackage.fragments.MyFragment$GetBuildings$1.run(MyFragment.java:130)
05-27 22:22:56.964: E/AndroidRuntime(26452): at android.os.Handler.handleCallback(Handler.java:615)
05-27 22:22:56.964: E/AndroidRuntime(26452): at android.os.Handler.dispatchMessage(Handler.java:92)
05-27 22:22:56.964: E/AndroidRuntime(26452): at android.os.Looper.loop(Looper.java:137)
05-27 22:22:56.964: E/AndroidRuntime(26452): at android.app.ActivityThread.main(ActivityThread.java:4867)
05-27 22:22:56.964: E/AndroidRuntime(26452): at java.lang.reflect.Method.invokeNative(Native Method)
05-27 22:22:56.964: E/AndroidRuntime(26452): at java.lang.reflect.Method.invoke(Method.java:511)
05-27 22:22:56.964: E/AndroidRuntime(26452): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
05-27 22:22:56.964: E/AndroidRuntime(26452): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
05-27 22:22:56.964: E/AndroidRuntime(26452): at dalvik.system.NativeStart.main(Native Method)
这里是片段(请注意,如果我放出AsyncTask,地图会正确显示):
public class MyFragment extends Fragment {
MapView mapView;
GoogleMap map;
private ProgressDialog pDialog;
private static String url = "http://mySite/query.php";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment, container, false);
mapView = (MapView) v.findViewById(R.id.map);
mapView.onCreate(savedInstanceState);
map = mapView.getMap();
map.getUiSettings().setMyLocationButtonEnabled(true);
map.setMyLocationEnabled(true);
MapsInitializer.initialize(this.getActivity());
LocationManager locationManager = (LocationManager) this.getActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
Location location = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true));
if (location != null)
{
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(new LatLng(location.getLatitude(), location.getLongitude()))
.zoom(14)
.bearing(0)
.tilt(0)
.build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
new GetBuildings().execute();
return v;
}
@Override
public void onResume() {
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
class GetBuildings extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String... params) {
getActivity().runOnUiThread(new Runnable()
{
LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
Location location = locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true));
public void run() {
JSONParser jparser = new JSONParser();
double lat = location.getLatitude();
double lon = location.getLongitude();
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("lat", Double.toString(lat)));
params.add(new BasicNameValuePair("lon", Double.toString(lon)));
JSONObject json = jparser.makeHttpRequest(
url, "POST", params);
try {
JSONArray jarray = json.getJSONArray("Buildings details");// NULLPOINTEREXCEPTION HERE
for(int i = 0; i < jarray.length(); i++)
{
JSONObject object = jarray.getJSONObject(i);
LatLng latlng = new LatLng(Double.parseDouble(object.getString("lat")),
Double.parseDouble(object.getString("lon")));
MarkerOptions mo = new MarkerOptions().position(latlng)
.title(object.getString("name"));
map.addMarker(mo);
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
});
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
}
JSONParser.java
public class JSONParser {
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public JSONParser() {
}
public JSONObject makeHttpRequest(String url, String method,
List<NameValuePair> params) {
try {
if(method == "POST"){
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}else if(method == "GET"){
DefaultHttpClient httpClient = new DefaultHttpClient();
String paramString = URLEncodedUtils.format(params, "utf-8");
url += "?" + paramString;
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
json = sb.toString();
} catch (Exception e) {
e.printStackTrace();
}
try {
jObj = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
return jObj;
}
}
query.php
<?php
$response = array();
$pi = 3.1415926535898;
$earth_radius = 6372.795477598;
$range= 40.0; //km
$mysqli = new mysqli("host", "user", "psw", "db");
$query = "SELECT id, name, city, lat, lon,
($earth_radius*ACOS(
(SIN($pi * $lat / 180)*SIN($pi * lat / 180)) +
(COS($pi * $lat / 180)*COS($pi * lat / 180) * COS(ABS(($pi * $lon / 180) - ($pi * lon / 180))) )
)
) as distance from BuildingsDetails HAVING distance<$range ORDER BY distance";
if ( (isset($_POST['lat'])) && (isset($_POST['lon'])) ) {
$lat = $_POST["lat"];
$lon = $_POST["lon"];
$result = $mysqli->query($query);
if ($result->num_rows > 0) {
$response["Buildings Details"] = array();
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
$buildingsdetails = array();
$buildingsdetails["id"] = $row["id"];
$buildingsdetails["name"] = $row["name"];
$buildingsdetails["city"] = $row["city"];
$buildingsdetails["lat"] = $row["lat"];
$buildingsdetails["lon"] = $row["lon"];
$buildingsdetails["distance"] = $row["distance"];
array_push($response["Buildings Details"], $buildingsdetails);
}
echo json_encode($response);
} else {
$response["message"] = "No buildings found";
echo json_encode($response);
}
} else {
$response["message"] = "Missing parameter(s)";
echo json_encode($response);
}
?>
请注意,如果我在脚本中手动设置lat和lon值,并在浏览器中输入URL,我会正确获取JSON,如下所示:
{"Buildings Details":[{"id":"3","name":"building1","city":"city1","lat":"52.5014076","lon":"13.4023285","distance":"26.2818230530031"},{"id":"5","name":"building2","city":"city2","lat":"52.379173","lon":"12.819091","distance":"26.4070424101156"},{"id":"26","name":"building3","city":"city3","lat":"52.656543","lon":"13.976542","distance":"32.5675097399059"}]}
所以我猜应用程序将纬度和经度参数传递给PHP脚本时会出现问题。有人有想法吗?
更新:我真的不知道发生了什么变化,但现在我没有收到任何错误。不幸的是,地图上没有标记显示。 Null JSON?
答案 0 :(得分:0)
你有问题:
getActivity().runOnUiThread(new Runnable() {..}
在android中,不允许在主线程上执行网络操作。
您的代码很可能没有访问PHP脚本,因此将导致null。