阅读JSONObejct时出现Google API Directions错误

时间:2017-10-21 18:43:42

标签: android json google-maps-android-api-2

在我的应用程序中,我使用Google地方选择器获取用户将前往的位置坐标,并使用Google API路线我获得KM的距离但有时我在日志中收到此错误并且没有获得距离和时间:

10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err: org.json.JSONException: Index 0 out of range [0..0)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at org.json.JSONArray.get(JSONArray.java:293)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at org.json.JSONArray.getJSONObject(JSONArray.java:521)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.ddz.assistenteauto.Fragments.TravelFragment$4.onResponse(TravelFragment.java:249)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.ddz.assistenteauto.Fragments.TravelFragment$4.onResponse(TravelFragment.java:236)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at android.os.Looper.loop(Looper.java:148)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7325)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
10-21 20:30:23.326 4920-4920/com.ddz.assistenteauto W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

以下是我如何使用http请求向Google发送请求:

private void getDistanceTime(TravelInfo obj){

    Log.d(TAG, "getDistanceTime()");
    // Instantiate the RequestQueue.
    RequestQueue queue = Volley.newRequestQueue(getActivity());

    String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getStartLat() + "," + obj.getStartLng() + "&destination=" + obj.getEndLat() + "," + obj.getEndLng() + "&mode=driving&sensor=false";

    // Request a string response from the provided URL.
    StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Display the first 500 characters of the response string.
                    //mTextView.setText("Response is: "+ response.substring(0,500));
                    //Log.i(TAG,"Response is: "+ response);

                    try {
                        JSONObject jsonObject = new JSONObject(response);

                        // routesArray contains ALL routes
                        JSONArray routesArray = jsonObject.getJSONArray("routes");
                        // Grab the first route
                        JSONObject route = routesArray.getJSONObject(0);
                        // Take all legs from the route
                        JSONArray legs = route.getJSONArray("legs");
                        // Grab first leg
                        JSONObject leg = legs.getJSONObject(0);
                        //take travel distance
                        JSONObject distanceObject = leg.getJSONObject("distance");
                        String distance = distanceObject.getString("text");
                        //Take travel duration
                        JSONObject durationObject = leg.getJSONObject("duration");
                        String duration = durationObject.getString("text");

                        //Set distance and duration to the class infoTravel that contain coordinates
                        setDistanceTime(distance, duration);


                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            //mTextView.setText("That didn't work!");
            Log.i(TAG,"That didn't work!");
        }
    });
    // Add the request to the RequestQueue.
    queue.add(stringRequest);

}

有人可以帮忙吗?

我可以从PlacePicker获得用户位置吗? 从现在开始,我用它来获取用户位置:

private void getUserLocation() {

    Log.i(TAG, "getUserLocation()");
    if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    mFusedLocationClient.getLastLocation()
            .addOnSuccessListener(getActivity(), new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {
                    // Got last known location. In some rare situations this can be null.
                    if (location != null) {
                        // Logic to handle location object
                        String stringStartLat, stringStartLng;

                        travelInfo.setStartLat(location.getLatitude());
                        travelInfo.setStartLng(location.getLongitude());
                        stringStartLat = Double.toString(travelInfo.getStartLat());
                        stringStartLng = Double.toString(travelInfo.getStartLng());
                        //Set the TextView in the fragment with start coordinates
                        startLatView.setText(stringStartLat);
                        startLngView.setText(stringStartLng);

                        if (travelInfo.getEndLat() != 0 && travelInfo.getEndLng() != 0) {
                            Log.i(TAG, "Dentro if userlocation");
                            getDistanceTime(travelInfo);
                        }
                    }
                }
            });
}

修改

当我收到JSON错误时,我会从Google API收到此JSON

10-21 20:54:18.965 22814-22814/com.ddz.assistenteauto I/TravelFragment: Response is: {
                                                                           "error_message" : "You have exceeded your daily request quota for this API. We recommend registering for a key at the Google Developers Console: https://console.developers.google.com/apis/credentials?project=_",
                                                                           "routes" : [],
                                                                           "status" : "OVER_QUERY_LIMIT"
                                                                        }

修改

我将密钥添加到网址但仍然收到错误:

String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getStartLat() + "," + obj.getStartLng() + "&destination=" + obj.getEndLat() + "," + obj.getEndLng() + "&mode=driving&AIza*****************FI";

现在使用密钥编辑2我收到此错误:

10-22 15:24:35.540 27362-27362/com.ddz.assistenteauto I/TravelFragment: Response is: {
                                                                           "error_message" : "Requests to this API must be over SSL. Load the API with \"https://\" instead of \"http://\".",
                                                                           "routes" : [],
                                                                           "status" : "REQUEST_DENIED"

所以我将http改为https ...让我们看看                                                                         }

1 个答案:

答案 0 :(得分:0)

错误消息非常明确,并且表示您超出了配额,且您的Directions API请求未使用API​​密钥。

请注意,对Google网络服务的无密钥访问使用共享配额,即使您没有发送太多请求,没有API密钥的其他用户也可以发送许多请求并使用公共配额。

要解决此问题,您必须在Google Cloud开发者控制台中创建项目,激活Directions API Web服务并生成API密钥。然后,您可以在请求中应用密钥:

String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + obj.getStartLat() + "," + obj.getStartLng() + "&destination=" + obj.getEndLat() + "," + obj.getEndLng() + "&mode=driving&key=YOUR_API_KEY";

您可以安全地删除sensor它已过时而不再需要。

有关详细信息,请参阅Directions API文档:

https://developers.google.com/maps/documentation/directions/get-api-key

<强>更新

您还应该在响应中正确处理status的可能值。有时您可以获得ZERO_RESULTS,NOT_FOUND或UNKNOWN_ERROR,在这种情况下,routes元素不存在或在响应中为空,这会导致您在代码中观察到异常。

try {
    JSONObject jsonObject = new JSONObject(response);

    //Get status first
    String status = jsonObject.getString("status");

    if (status.equals("OK")) {
        // routesArray contains ALL routes
        JSONArray routesArray = jsonObject.getJSONArray("routes");
        // Grab the first route
        JSONObject route = routesArray.getJSONObject(0);
        // Take all legs from the route
        JSONArray legs = route.getJSONArray("legs");
        // Grab first leg
        JSONObject leg = legs.getJSONObject(0);
        //take travel distance
        JSONObject distanceObject = leg.getJSONObject("distance");
        String distance = distanceObject.getString("text");
        //Take travel duration
        JSONObject durationObject = leg.getJSONObject("duration");
        String duration = durationObject.getString("text");
        //Set distance and duration to the class infoTravel that contain coordinates
        setDistanceTime(distance, duration);
    } else if (status.equals("NOT_FOUND")) {
        //TODO: handle not found
    } else if (status.equals("ZERO_RESULTS")) {
        //TODO: handle zero results
    } else if (status.equals("OVER_QUERY_LIMIT")) {
        //TODO: handle over query limit
    }
    .....

} catch (JSONException e) {
    e.printStackTrace();
}

            }

希望这有帮助!