Android中Google地圖路徑導航,使用mapfragment地圖上畫出線路(google map api v2)詳解

在這篇裏咱們只聊怎麼在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 }
View Code

 

分析: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畫線路導航的方法就講完了,淪落凡間 已使用沒有問題,有疑問能夠在下面提出來。

相關文章
相關標籤/搜索