在正在进行的项目中,需要找出地图中起点到终点的行车路线以及距离和相应的时间,这里我们用Google Directions API来实现。
Google Directions API 请求是以下形式的 HTTP 网址:http://maps.googleapis.com/maps/api/directions/output?parameters
其中,output 可能是以下任何一个值:
1、json(建议)表示以 JavaScript 对象表示法 (JSON) 的形式输出;
2、xml 表示以 XML 的形式输出;
具体参数参见https://developers.google.com/maps/documentation/directions/?hl=zh-CN
注意事项:由于我实在android4.0以上的版本上调用Http请求,出现了android.os.NetworkOnMainThreadException异常,所以采用了AsyncTask。
下面贴上具体的代码:
1、运行Http请求的容器,也就是自定义的继承AsyncTask的GetRouteTask类框架:
private class GetRouteTask extends AsyncTask<String, Void, JSONObject>{ @Override protected void onPreExecute() { } @Override protected JSONObject doInBackground(String... url) { // TODO Auto-generated method stub return getRouteFromURL(url[0]); } @Override protected void onPostExecute(JSONObject result) { } /* * 根据URL通过Http请求远程调用Google Directions API * 并将所要的数据封装到JSONObject中 */ private JSONObject getRouteFromURL(String url){ } /** * 解析返回overview_polyline的路线编码 * * @param encoded * @return */ private List<GeoPoint> decodePoly(String encoded) { } } |
如上处理之后,可以在高版本的android上解决 NetworkOnMainThreadException异常了。然后只需在需要用到的地方调用new GetRouteTask().execute(url)即可。具体的AsyncTask类的使用请详见相应的API
2、下面进入正题,来看一下具体的getRouteFromURL方法的代码,如下:
HttpGet get = new HttpGet(url); String strResponse = null; try { HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 8000); HttpClient httpClient = new DefaultHttpClient(httpParameters); HttpResponse httpResponse = httpClient.execute(get); Log.e("tag1","tage1"); if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ strResponse = EntityUtils.toString(httpResponse.getEntity()); } } catch (Exception e) { Log.e("tag3",e.toString()); return null; } if(strResponse == null){ return null; } try { JSONObject jsonResponse = new JSONObject(strResponse); JSONArray routes = jsonResponse.getJSONArray("routes"); Log.e("JSONArray", Integer.toString(routes.length())); JSONObject route = routes.getJSONObject(0); JSONArray legs = route.getJSONArray("legs"); JSONObject distance = legs.getJSONObject(0).getJSONObject("distance"); JSONObject duration = legs.getJSONObject(0).getJSONObject("duration"); JSONObject polyline = route.getJSONObject("overview_polyline"); List<GeoPoint> listOfGeoPoint = decodePoly(polyline.getString("points")); JSONArray geoPoints = new JSONArray(); for(int i=0; i<listOfGeoPoint.size(); i++){ geoPoints.put(i, listOfGeoPoint.get(i)); } JSONObject result = new JSONObject(); result.put("distance", distance.getString("text")); result.put("duration", duration.getString("text")); result.put("geoPoints", geoPoints); Log.e("geoPoints", ((GeoPoint)geoPoints.get(0)).toString()); return result; } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; |
在JSON解析的过程中,需要了解JSON的格式,如JSONObject和JSONArray。 JSONObject格式如:{ "firstName": "Brett" },一般有{}包括着,然后是key和value。JSONArray格式如:
{ "people": [
{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },
{ "firstName": "Jason", "lastName":"Hunter", "email": "bbbb"},
{ "firstName": "Elliotte", "lastName":"Harold", "email": "cccc" }
]}
上面的例子是一个JSONObject包含着一个JSONArray,而JSONArray中包含着三个JSONObject,每个JSONObject中又有多个键值对。
详细请参考http://baike.baidu.com/view/136475.htm
在Google Directions API的返回结果中routes键所对应的JSONArray的下一级只有一个{},故只包含一个JSONObject,该JSONObject又包含了普通的键值对、JSONObject和JSONArray,笔者在开发的过程中疏忽了,花费了好长时间,这里请读者注意。
3、然后是对overview_polyline的路线编码的解码(这个是引用网上的资料,链接是http://blog.csdn.net/ccgang/article/details/6328671)
List<GeoPoint> poly = new ArrayList<GeoPoint>(); int index = 0, len = encoded.length(); int lat = 0, lng = 0; while (index < len) { int b, shift = 0, result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lat += dlat; shift = 0; result = 0; do { b = encoded.charAt(index++) - 63; result |= (b & 0x1f) << shift; shift += 5; } while (b >= 0x20); int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); lng += dlng; GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6), (int) (((double) lng / 1E5) * 1E6)); poly.add(p); } return poly; |