在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系统中需要的google play services等另行查看资料,沦落凡间不详述。

参考:https://developers.google.com/maps/documentation/android/intro

首先我们在Activity上加载一个GoogleMap,然后再在Map上画上标记和路径导航。

先上主要代码:

  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. @Override
  16. protected void onCreate(Bundle arg0) {
  17. super.onCreate(arg0);
  18. init();
  19. findViewById();
  20. setListenter();
  21. processLogic();
  22. getDirection();
  23. }
  24.  
  25. /**
  26. * Get the direction
  27. */
  28. private void getDirection() {
  29. FoundRoadRouteTask task = new FoundRoadRouteTask(onFoundRoadRouteTaskListener);
  30. task.execute(new String[] {locLat+","+locLng, lat + "," + lng });
  31. }
  32.  
  33. /**
  34. * Draw route information
  35. */
  36. private void drawRoute() {
  37. try {
  38. // Draw route info
  39. map.addMarker(new MarkerOptions().position(latlngs.get(0)).title(address).visible(true));
  40. PolylineOptions lineOptions = new PolylineOptions();
  41. lineOptions.width(5);
  42. for (int i = 0; i < latlngs.size() - 1; i++) {
  43. lineOptions.add(latlngs.get(i));
  44. }
  45. map.addPolyline(lineOptions);
  46. } catch (Exception e) {
  47.  
  48. }
  49. }
  50.  
  51. private OnFounedRoadRouteListener onFoundRoadRouteTaskListener = new OnFounedRoadRouteListener() {
  52.  
  53. @SuppressWarnings("unchecked")
  54. @Override
  55. public void found(Object obj) {
  56. if (obj != null) {
  57. List<LatLng> tempLats = (List<LatLng>) obj;
  58. latlngs.addAll(tempLats);
  59. }
  60. drawRoute();
  61. }
  62. };
  63.  
  64. private void getLatLng() {
  65. try {
  66. Intent latlngIntent = getIntent();
  67. Bundle b = latlngIntent.getBundleExtra("latlng");
  68. lat = b.getDouble("lat");
  69. lng = b.getDouble("lng");
  70. address = b.getString("address");
  71. } catch (Exception e) {
  72.  
  73. }
  74. }
  75.  
  76. protected void init() {
  77. setContentView(R.layout.direction_layout);
  78. getLatLng();
  79. btnBack = (Button) this.findViewById(R.direction_layout.btn_back);
  80. }
  81.  
  82. protected void processLogic() {
  83.  
  84. locLat=application.getLatitude();
  85. locLng=application.getLongitude();
  86.  
  87. FragmentManager manager = getSupportFragmentManager();
  88. mapFragment = (SupportMapFragment) manager
  89. .findFragmentById(R.direction_layout.map);
  90. map = mapFragment.getMap();
  91. initMap();
  92. }
  93.  
  94. protected void setListenter() {
  95. btnBack.setOnClickListener(onBackClickListener);
  96. }
  97.  
  98. /**
  99. * Initialize the map
  100. */
  101. private void initMap() {
  102. try {
  103. //设置在地图上显示手机的位置,和显示控制按钮
  104. map.setMyLocationEnabled(true);
  105. //设置室内地图是否开启
  106. map.setIndoorEnabled(true);
  107. //设置地图类型三种:1:MAP_TYPE_NORMAL: Basic map with roads.
  108. //2:MAP_TYPE_SATELLITE: Satellite view with roads.3:MAP_TYPE_TERRAIN: Terrain view without roads.
  109. map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
  110. // map.setTrafficEnabled(true);
  111. map.setOnMapLongClickListener(onMapLongClickListener);
  112.  
  113. GPSUtil gpsUtil = new GPSUtil();
  114. gpsUtil.startLocation(this, getContentResolver(),
  115. onLocationChangedListener);
  116.  
  117. locationManager = (LocationManager) this
  118. .getSystemService(Context.LOCATION_SERVICE);
  119. location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
  120. } catch (Exception e) {
  121.  
  122. }
  123. }
  124.  
  125. /** On Location change listener */
  126. private OnLocationChangedListener onLocationChangedListener = new OnLocationChangedListener() {
  127.  
  128. @Override
  129. public void onLocationChanged(Location location) {
  130. // To get the local latitude and longitude and set the map view to
  131. // the position
  132. if (location != null) {
  133. locLat = location.getLatitude();
  134. locLng = location.getLongitude();
  135. locLatLng = new LatLng(locLat, locLng);
  136. map.moveCamera(CameraUpdateFactory.newLatLng(locLatLng));
  137. map.moveCamera(CameraUpdateFactory.zoomTo(15));
  138. }
  139. }
  140. };
  141.  
  142. /** On Map long click listener */
  143. private OnMapLongClickListener onMapLongClickListener = new OnMapLongClickListener() {
  144.  
  145. @Override
  146. public void onMapLongClick(LatLng latlng) {
  147. Location location = new Location("LongPressLocationProvider");
  148. location.setLatitude(latlng.latitude);
  149. location.setLongitude(latlng.longitude);
  150. //设置精度
  151. location.setAccuracy(20);
  152. onLocationChangedListener.onLocationChanged(location);
  153. }
  154. };
  155.  
  156. private OnClickListener onBackClickListener = new OnClickListener() {
  157.  
  158. @Override
  159. public void onClick(View v) {
  160. DirectionActivity.this.finish();
  161. }
  162. };
  163. }

分析:

  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. }

在这个方法中我们从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对象来画标记和线路。

  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. }

这个方法用来初始化地图,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)设置移动后视角镜头大小。

  1. private void getDirection() {
  2. FoundRoadRouteTask task = new FoundRoadRouteTask(onFoundRoadRouteTaskListener);
  3. task.execute(new String[] {locLat+","+locLng, lat + "," + lng });
  4. }

这个方法为启动一个异步线程处理向gooogle服务器请求路线规划,传入起点和目的地的经纬度。FoundRoadRouteTask继承了AsyncTask。等下讲请求的地址和处理方法。

  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. }

这个方法就是画出线路的主要方法了,第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>标签中有编码的线路导航坐标点经纬度,且已经接近于平滑,方法如下:

  1. List<LatLng> points=new ArrayList<LatLng>();
    if (-1 == strResult.indexOf("<status>OK</status>")){
  2. return null;
  3. }
  4.  
  5. int pos = strResult.indexOf("<overview_polyline>");
  6. pos = strResult.indexOf("<points>", pos + 1);
  7. int pos2 = strResult.indexOf("</points>", pos);
  8. strResult = strResult.substring(pos + 8, pos2);
  9.  
  10. List<GeoPoint> geoPoints = decodePoly(strResult);
  11. // Log.i("tag", "geoPoints:"+geoPoints.toString());
  12. LatLng ll;
  13. Log.i("tag", "geopoints.size:"+geoPoints.size());
  14. for(Iterator<GeoPoint> gpit=geoPoints.iterator();gpit.hasNext();){
  15. GeoPoint gp=gpit.next();
  16. double latitude=gp.getLatitudeE6();
  17. latitude=latitude/1000000;
  18. // Log.i("tag", "latitude:"+latitude);
  19. double longitude=gp.getLongitudeE6();
  20. longitude=longitude/1000000;
  21. // Log.i("tag", "longitude:"+longitude);
  22. ll=new LatLng(latitude, longitude);
  23. points.add(ll);
  24. }
  25. // Log.i("tag", "points:"+points.toString());
  26.  
  27. 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画线路导航的方法就讲完了,沦落凡间 已使用没有问题,有疑问可以在下面提出来。

Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解的更多相关文章

  1. Google Map API使用详解(一)——Google Map开发背景知识

    一.谷歌地图主页 谷歌地图对应不同的地区都会有一些专门的主页,首次登陆时会显示这些地区.比如,香港的:http://maps.google.com.hk,台湾的:http://maps.google. ...

  2. Android中获取文件路径的方法总结及对照

    最近在写文件存贮,Android中获取文件路径的方法比较多,所以自己也很混乱.找了好几篇博客,发现了以下的路径归纳,记录一下,以备不时之需 Environment.getDataDirectory() ...

  3. Android百度地图SDK 导航初始化和地图初始化引起的冲突

    如题,相同是百度地图SDK开发过程中遇到的一个问题.交代下背景: 开发了一款内嵌百度地图的应用,因此里面差点儿相同将眼下百度地图SDK开放的主要功能都用到了,定位,地图显示,覆盖物标示.POI搜索,行 ...

  4. Google Map API v2 步步为营(一) ----- 初见地图

    官方文档:https://developers.google.com/maps/documentation/android/start?hl=zh-CN 先谷歌后百度.使用google的api基本上按 ...

  5. Android API Levels 详解

    Android API Levels 当你开发你的Android应用程序时,了解该平台API变更管理的基本方法和概念是很有帮助的.同样的,知道API级别标识以及该标识如何保障你的应用与实际硬件设备相兼 ...

  6. android Camera2 API使用详解

    原文:android Camera2 API使用详解 由于最近需要使用相机拍照等功能,鉴于老旧的相机API问题多多,而且新的设备都是基于安卓5.0以上的,于是本人决定研究一下安卓5.0新引入的Came ...

  7. js数组中foEach和map的用法详解 jq中的$.each和$.map

    数组中foEach和map的用法详解 相同点: 1.都是循环遍历数组(仅仅是数组)中的每一项. 2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项value, ...

  8. Android中访问sdcard路径的几种方式

    以前的Android(4.1之前的版本)中,SDcard路径通过"/sdcard"或者"/mnt/sdcard"来表示,而在JellyBean(安卓4.1)系统 ...

  9. Google Map API v2 (四)----- 导航路径

    仍然是建议个异步小任务 private GetPathTask mGetPathTask = null; private void getGuidePath(LatLng origin){ if(mG ...

随机推荐

  1. Ventuz配置Leap Motion环境

    1.下载Leap Dev Kit 前往官网www.leapmotion.com,下载相应平台的开发包,目前PC版的最新版本为2.3.1. SDK里包含了Leap Motion的安装包,上图第二个.安装 ...

  2. hdu1565 网络流或状态压缩DP

    对于网络流有一个定理: 最小点权覆盖集=最大网络流: 最大点权独立集=总权值-最小点权覆盖集: 网络流解法代码如下: #include<cstdio> #include<iostre ...

  3. shell脚本字符串截取的8种方法

    假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. echo ${var#*//} 其中 var 是变量名,# 号是运算符,*/ ...

  4. SQL Server的三种物理连接之Hash Join(三)

    简介 在 SQL Server 2012 在一些特殊的例子下会看到下面的图标: Hash Join分为两个阶段,分别为生成和探测阶段. 首先是生成阶段,将输入源中的每一个条目经过散列函数的计算都放到不 ...

  5. sql server 2008 查询语句的红色波浪线

    在 Microsoft sql server management studio 里点击“编辑”——“IntelliSense”——“刷新本地缓存” 就会发现红色波浪线没了(前提是你的代码没错)

  6. OpenGL3-绘制各种图元绘制

    代码下载 #include "CELLWinApp.hpp"#include <gl/GLU.h>#include <assert.h>#include & ...

  7. 前端面试题和setTimeout异步

    var len=4; while(len--){ setTimeout(function(){ alert(len); },0); alert(len); } 这个题目的答案我先说出来,读者请仔细考虑 ...

  8. Jquery 自定义事件实现发布/订阅

    //用户点击logoff按钮时,广播一个自定义事件,给任何需要保存状态的感兴趣的观察者,然后导航到logoff页面 $('#logoff').click(function(){ $.event.tri ...

  9. 查看mysql集群状态是否正常

    如何查看mysql集群状态是否正常: 进入mysql 输入show status like 'wsrep%': 查看cluster sizes 是否为3

  10. emacs_1

    --> 正在处理依赖关系 perl(VMS::Filespec),它被软件包 perl-PathTools-3.2701-1.el5.rf.x86_64 需要---> 软件包 perl-p ...