JSON解析(找不到对象)

时间:2014-05-27 21:28:31

标签: java php android mysql json

我正在开发一款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?

1 个答案:

答案 0 :(得分:0)

你有问题:

getActivity().runOnUiThread(new Runnable() {..}

在android中,不允许在主线程上执行网络操作。

您的代码很可能没有访问PHP脚本,因此将导致null。