在這篇裏咱們只聊怎麼在android中google map api v2地圖上畫出路徑導航,用mapfragment而不是mapview,至於怎麼去申請key,manifest.xml中加入的權限,系統中須要的google play services等另行查看資料,淪落凡間不詳述。html
參考:https://developers.google.com/maps/documentation/android/introandroid
首先咱們在Activity上加載一個GoogleMap,而後再在Map上畫上標記和路徑導航。git
先上主要代碼:json
1 public class DirectionActivity extends FragmentActivity { 2 private Button btnBack; 3 private SupportMapFragment mapFragment; 4 private GoogleMap map; 5 private LocationManager locationManager; 6 private Location location; 7 private List<LatLng> latlngs = new ArrayList<LatLng>(); 8 private double lat; 9 private double lng; 10 private String address; 11 private double locLat; 12 private double locLng; 13 private LatLng locLatLng; 14 15 16 @Override 17 protected void onCreate(Bundle arg0) { 18 super.onCreate(arg0); 19 init(); 20 findViewById(); 21 setListenter(); 22 processLogic(); 23 getDirection(); 24 } 25 26 /** 27 * Get the direction 28 */ 29 private void getDirection() { 30 FoundRoadRouteTask task = new FoundRoadRouteTask(onFoundRoadRouteTaskListener); 31 task.execute(new String[] {locLat+","+locLng, lat + "," + lng }); 32 } 33 34 /** 35 * Draw route information 36 */ 37 private void drawRoute() { 38 try { 39 // Draw route info 40 map.addMarker(new MarkerOptions().position(latlngs.get(0)).title(address).visible(true)); 41 PolylineOptions lineOptions = new PolylineOptions(); 42 lineOptions.width(5); 43 for (int i = 0; i < latlngs.size() - 1; i++) { 44 lineOptions.add(latlngs.get(i)); 45 } 46 map.addPolyline(lineOptions); 47 } catch (Exception e) { 48 49 } 50 } 51 52 private OnFounedRoadRouteListener onFoundRoadRouteTaskListener = new OnFounedRoadRouteListener() { 53 54 @SuppressWarnings("unchecked") 55 @Override 56 public void found(Object obj) { 57 if (obj != null) { 58 List<LatLng> tempLats = (List<LatLng>) obj; 59 latlngs.addAll(tempLats); 60 } 61 drawRoute(); 62 } 63 }; 64 65 private void getLatLng() { 66 try { 67 Intent latlngIntent = getIntent(); 68 Bundle b = latlngIntent.getBundleExtra("latlng"); 69 lat = b.getDouble("lat"); 70 lng = b.getDouble("lng"); 71 address = b.getString("address"); 72 } catch (Exception e) { 73 74 } 75 } 76 77 protected void init() { 78 setContentView(R.layout.direction_layout); 79 getLatLng(); 80 btnBack = (Button) this.findViewById(R.direction_layout.btn_back); 81 } 82 83 protected void processLogic() { 84 85 locLat=application.getLatitude(); 86 locLng=application.getLongitude(); 87 88 FragmentManager manager = getSupportFragmentManager(); 89 mapFragment = (SupportMapFragment) manager 90 .findFragmentById(R.direction_layout.map); 91 map = mapFragment.getMap(); 92 initMap(); 93 } 94 95 protected void setListenter() { 96 btnBack.setOnClickListener(onBackClickListener); 97 } 98 99 /** 100 * Initialize the map 101 */ 102 private void initMap() { 103 try { 104 //設置在地圖上顯示手機的位置,和顯示控制按鈕 105 map.setMyLocationEnabled(true); 106 //設置室內地圖是否開啓 107 map.setIndoorEnabled(true); 108 //設置地圖類型三種:1:MAP_TYPE_NORMAL: Basic map with roads. 109 //2:MAP_TYPE_SATELLITE: Satellite view with roads.3:MAP_TYPE_TERRAIN: Terrain view without roads. 110 map.setMapType(GoogleMap.MAP_TYPE_NORMAL); 111 // map.setTrafficEnabled(true); 112 map.setOnMapLongClickListener(onMapLongClickListener); 113 114 GPSUtil gpsUtil = new GPSUtil(); 115 gpsUtil.startLocation(this, getContentResolver(), 116 onLocationChangedListener); 117 118 locationManager = (LocationManager) this 119 .getSystemService(Context.LOCATION_SERVICE); 120 location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 121 } catch (Exception e) { 122 123 } 124 } 125 126 /** On Location change listener */ 127 private OnLocationChangedListener onLocationChangedListener = new OnLocationChangedListener() { 128 129 @Override 130 public void onLocationChanged(Location location) { 131 // To get the local latitude and longitude and set the map view to 132 // the position 133 if (location != null) { 134 locLat = location.getLatitude(); 135 locLng = location.getLongitude(); 136 locLatLng = new LatLng(locLat, locLng); 137 map.moveCamera(CameraUpdateFactory.newLatLng(locLatLng)); 138 map.moveCamera(CameraUpdateFactory.zoomTo(15)); 139 } 140 } 141 }; 142 143 /** On Map long click listener */ 144 private OnMapLongClickListener onMapLongClickListener = new OnMapLongClickListener() { 145 146 @Override 147 public void onMapLongClick(LatLng latlng) { 148 Location location = new Location("LongPressLocationProvider"); 149 location.setLatitude(latlng.latitude); 150 location.setLongitude(latlng.longitude); 151 //設置精度 152 location.setAccuracy(20); 153 onLocationChangedListener.onLocationChanged(location); 154 } 155 }; 156 157 private OnClickListener onBackClickListener = new OnClickListener() { 158 159 @Override 160 public void onClick(View v) { 161 DirectionActivity.this.finish(); 162 } 163 }; 164 }
分析:api
1 private void getLatLng() { 2 try { 3 Intent latlngIntent = getIntent(); 4 Bundle b = latlngIntent.getBundleExtra("latlng"); 5 lat = b.getDouble("lat"); 6 lng = b.getDouble("lng"); 7 address = b.getString("address"); 8 } catch (Exception e) { 9
10 } 11 }
在這個方法中咱們從intent中拿到啓動這個fragmentActivity時傳過來的目的地經緯度。服務器
1 protected void processLogic() { 2 3 locLat=application.getLatitude(); 4 locLng=application.getLongitude(); 5 6 FragmentManager manager = getSupportFragmentManager(); 7 mapFragment = (SupportMapFragment) manager 8 .findFragmentById(R.direction_layout.map); 9 map = mapFragment.getMap(); 10 initMap(); 11 }
這裏的3,4行爲拿到當前本地的經緯度,application爲一個Application類的對象,裏面寫有get方法,能夠拿到當前本地經緯度。6,7行爲獲得mapFragment對象。9行爲經過mapFragment得到GoogleMap對象,後面咱們就是用這個map對象來畫標記和線路。app
1 private void initMap() { 2 try { 3 //設置在地圖上顯示手機的位置,和顯示控制按鈕 4 map.setMyLocationEnabled(true); 5 //設置室內地圖是否開啓 6 map.setIndoorEnabled(true); 7 //設置地圖類型三種:1:MAP_TYPE_NORMAL: Basic map with roads. 8 //2:MAP_TYPE_SATELLITE: Satellite view with roads.3:MAP_TYPE_TERRAIN: Terrain view without roads. 9 map.setMapType(GoogleMap.MAP_TYPE_NORMAL); 10 // map.setTrafficEnabled(true); 11 map.setOnMapLongClickListener(onMapLongClickListener); 12 13 GPSUtil gpsUtil = new GPSUtil(); 14 gpsUtil.startLocation(this, getContentResolver(), 15 onLocationChangedListener); 16 17 locationManager = (LocationManager) this 18 .getSystemService(Context.LOCATION_SERVICE); 19 location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); 20 } catch (Exception e) { 21
22 } 23 }
這個方法用來初始化地圖,3-11行爲地圖的設置,更多請查看:http://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html 。13-19行的GPSUtil爲一個監聽本地位置改變的類,當手機位置移動時GPS會獲得移動後的經緯度。異步
1 private OnLocationChangedListener onLocationChangedListener = new OnLocationChangedListener() { 2 3 @Override 4 public void onLocationChanged(Location location) { 5 // To get the local latitude and longitude and set the map view to 6 // the position 7 if (location != null) { 8 locLat = location.getLatitude(); 9 locLng = location.getLongitude(); 10 locLatLng = new LatLng(locLat, locLng); 11 map.moveCamera(CameraUpdateFactory.newLatLng(locLatLng)); 12 map.moveCamera(CameraUpdateFactory.zoomTo(15)); 13 } 14 } 15 };
這個匿名類裏的方法設置了當位置改變後地圖上指示點和鏡頭的變化,拿到經緯度後用一個LatLng類的對象來存放,11,22行設置視角的移動,moveCamera方法傳入的是一個CameraUpdate對象,該對象可用CameraUpdateFactory來生成,傳入CameraUpdateFactory.newLatLng(locLatLng)移動到這個新的經緯度的位置,CameraUpdateFactory.zoomTo(15)設置移動後視角鏡頭大小。ide
1 private void getDirection() { 2 FoundRoadRouteTask task = new FoundRoadRouteTask(onFoundRoadRouteTaskListener); 3 task.execute(new String[] {locLat+","+locLng, lat + "," + lng }); 4 }
這個方法爲啓動一個異步線程處理向gooogle服務器請求路線規劃,傳入起點和目的地的經緯度。FoundRoadRouteTask繼承了AsyncTask。等下講請求的地址和處理方法。this
1 private OnFounedRoadRouteListener onFoundRoadRouteTaskListener = new OnFounedRoadRouteListener() { 2 3 @SuppressWarnings("unchecked") 4 @Override 5 public void found(Object obj) { 6 if (obj != null) { 7 List<LatLng> tempLats = (List<LatLng>) obj; 8 latlngs.addAll(tempLats); 9 } 10 drawRoute(); 11 } 12 };
從這個回調方法中獲得處理好的LatLng對象,裏面存放了用來畫出線路的全部點的經緯度(把點連成線)。
1 /** 2 * Draw route information 3 */ 4 private void drawRoute() { 5 try { 6 // Draw route info 7 map.addMarker(new MarkerOptions().position(latlngs.get(0)).title(address).visible(true)); 8 PolylineOptions lineOptions = new PolylineOptions(); 9 lineOptions.width(5); 10 for (int i = 0; i < latlngs.size() - 1; i++) { 11 lineOptions.add(latlngs.get(i)); 12 } 13 map.addPolyline(lineOptions); 14 } catch (Exception e) { 15
16 } 17 }
這個方法就是畫出線路的主要方法了,第7行在地圖上標記出手機的當前位置,經過GoogleMap的addMarker方法,傳入一個MarkerOptions類型的對象,該對象設置了標記的信息,如:.position(LatLng latlng)設置地點,.title(String address)設置標記顯示的地點名稱,.visible(boolean b)設置標記是否可見。咱們能夠在map上畫線段[addPolyline(PolylineOptions options)],多邊形[addPolygon(PolygonOptions options)],圓[addCircle(CircleOptions options)],圖像[addGroundOverlay(GroundOverlayOptions options)]。傳入的都是一個PolygonOptions類型的對象,該對象定義了你所畫的圖形,咱們畫線路導航因此用addPolyline(),並使用PolygonOptions.add(LatLng... points)方法添加多個點的座標(7-12行),lineOptions.width(5);設置了所畫線的寬度(自行調整數值),最後用GoogleMap對象的addPolyline()方法畫出路線導航。
下面是請求和處理路線座標經緯度的方法:
1:首先咱們向這個地此發送http請求(這個應該沒問題吧):http://maps.google.com/maps/api/directions/xml?origin=[lat],[lng]&destination=[lat],[lng]&sensor=false&mode=driving
地址中的origin=[lat],[lng]爲起始地的緯度和經度,destination=[lat],[lng]爲目的地的緯度和經度(用double類型的經緯度數據替換中括號),xml爲設置返回的數據格式爲xml格式,也能夠寫爲json。mode=driving爲設置出行模式了駕駛,還有步行等方式,詳細可參考首段中的api文檔地址。
2:處理http請求返回的字符串(String strResult),在<overview_polyline>標籤中有編碼的線路導航座標點經緯度,且已經接近於平滑,方法以下:
List<LatLng> points=new ArrayList<LatLng>();
if (-1 == strResult.indexOf("<status>OK</status>")){ return null; } int pos = strResult.indexOf("<overview_polyline>"); pos = strResult.indexOf("<points>", pos + 1); int pos2 = strResult.indexOf("</points>", pos); strResult = strResult.substring(pos + 8, pos2); List<GeoPoint> geoPoints = decodePoly(strResult); // Log.i("tag", "geoPoints:"+geoPoints.toString()); LatLng ll; Log.i("tag", "geopoints.size:"+geoPoints.size()); for(Iterator<GeoPoint> gpit=geoPoints.iterator();gpit.hasNext();){ GeoPoint gp=gpit.next(); double latitude=gp.getLatitudeE6(); latitude=latitude/1000000; // Log.i("tag", "latitude:"+latitude); double longitude=gp.getLongitudeE6(); longitude=longitude/1000000; // Log.i("tag", "longitude:"+longitude); ll=new LatLng(latitude, longitude); points.add(ll); } // Log.i("tag", "points:"+points.toString()); return points;
1 /** 2 * Parses the returned lines of code of XML overview_polyline 3 * 4 * @return List<GeoPoint> 5 */ 6 private List<GeoPoint> decodePoly(String encoded) { 7 8 List<GeoPoint> poly = new ArrayList<GeoPoint>(); 9 int index = 0, len = encoded.length(); 10 int lat = 0, lng = 0; 11 12 while (index < len) { 13 int b, shift = 0, result = 0; 14 do { 15 b = encoded.charAt(index++) - 63; 16 result |= (b & 0x1f) << shift; 17 shift += 5; 18 } while (b >= 0x20); 19 int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 20 lat += dlat; 21 22 shift = 0; 23 result = 0; 24 do { 25 b = encoded.charAt(index++) - 63; 26 result |= (b & 0x1f) << shift; 27 shift += 5; 28 } while (b >= 0x20); 29 int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1)); 30 lng += dlng; 31 32 GeoPoint p = new GeoPoint((int) ((lat / 1E5) * 1E6), 33 (int) ((lng / 1E5) * 1E6)); 34 poly.add(p); 35 } 36 37 return poly; 38 }
這樣返回的列表points中存放的點即爲咱們要用來畫線路的座標點了。
到此android用google map api v2畫線路導航的方法就講完了,淪落凡間 已使用沒有問題,有疑問能夠在下面提出來。