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

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

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

先上主要代码:

 public class DirectionActivity extends FragmentActivity {
private Button btnBack;
private SupportMapFragment mapFragment;
private GoogleMap map;
private LocationManager locationManager;
private Location location;
private List<LatLng> latlngs = new ArrayList<LatLng>();
private double lat;
private double lng;
private String address;
private double locLat;
private double locLng;
private LatLng locLatLng; @Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
init();
findViewById();
setListenter();
processLogic();
getDirection();
} /**
* Get the direction
*/
private void getDirection() {
FoundRoadRouteTask task = new FoundRoadRouteTask(onFoundRoadRouteTaskListener);
task.execute(new String[] {locLat+","+locLng, lat + "," + lng });
} /**
* Draw route information
*/
private void drawRoute() {
try {
// Draw route info
map.addMarker(new MarkerOptions().position(latlngs.get(0)).title(address).visible(true));
PolylineOptions lineOptions = new PolylineOptions();
lineOptions.width(5);
for (int i = 0; i < latlngs.size() - 1; i++) {
lineOptions.add(latlngs.get(i));
}
map.addPolyline(lineOptions);
} catch (Exception e) { }
} private OnFounedRoadRouteListener onFoundRoadRouteTaskListener = new OnFounedRoadRouteListener() { @SuppressWarnings("unchecked")
@Override
public void found(Object obj) {
if (obj != null) {
List<LatLng> tempLats = (List<LatLng>) obj;
latlngs.addAll(tempLats);
}
drawRoute();
}
}; private void getLatLng() {
try {
Intent latlngIntent = getIntent();
Bundle b = latlngIntent.getBundleExtra("latlng");
lat = b.getDouble("lat");
lng = b.getDouble("lng");
address = b.getString("address");
} catch (Exception e) { }
} protected void init() {
setContentView(R.layout.direction_layout);
getLatLng();
btnBack = (Button) this.findViewById(R.direction_layout.btn_back);
} protected void processLogic() { locLat=application.getLatitude();
locLng=application.getLongitude(); FragmentManager manager = getSupportFragmentManager();
mapFragment = (SupportMapFragment) manager
.findFragmentById(R.direction_layout.map);
map = mapFragment.getMap();
initMap();
} protected void setListenter() {
btnBack.setOnClickListener(onBackClickListener);
} /**
* Initialize the map
*/
private void initMap() {
try {
//设置在地图上显示手机的位置,和显示控制按钮
map.setMyLocationEnabled(true);
//设置室内地图是否开启
map.setIndoorEnabled(true);
//设置地图类型三种:1:MAP_TYPE_NORMAL: Basic map with roads.
//2:MAP_TYPE_SATELLITE: Satellite view with roads.3:MAP_TYPE_TERRAIN: Terrain view without roads.
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// map.setTrafficEnabled(true);
map.setOnMapLongClickListener(onMapLongClickListener); GPSUtil gpsUtil = new GPSUtil();
gpsUtil.startLocation(this, getContentResolver(),
onLocationChangedListener); locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} catch (Exception e) { }
} /** On Location change listener */
private OnLocationChangedListener onLocationChangedListener = new OnLocationChangedListener() { @Override
public void onLocationChanged(Location location) {
// To get the local latitude and longitude and set the map view to
// the position
if (location != null) {
locLat = location.getLatitude();
locLng = location.getLongitude();
locLatLng = new LatLng(locLat, locLng);
map.moveCamera(CameraUpdateFactory.newLatLng(locLatLng));
map.moveCamera(CameraUpdateFactory.zoomTo(15));
}
}
}; /** On Map long click listener */
private OnMapLongClickListener onMapLongClickListener = new OnMapLongClickListener() { @Override
public void onMapLongClick(LatLng latlng) {
Location location = new Location("LongPressLocationProvider");
location.setLatitude(latlng.latitude);
location.setLongitude(latlng.longitude);
//设置精度
location.setAccuracy(20);
onLocationChangedListener.onLocationChanged(location);
}
}; private OnClickListener onBackClickListener = new OnClickListener() { @Override
public void onClick(View v) {
DirectionActivity.this.finish();
}
};
}

分析:

     private void getLatLng() {
try {
Intent latlngIntent = getIntent();
Bundle b = latlngIntent.getBundleExtra("latlng");
lat = b.getDouble("lat");
lng = b.getDouble("lng");
address = b.getString("address");
} catch (Exception e) {

}
}

在这个方法中我们从intent中拿到启动这个fragmentActivity时传过来的目的地经纬度。

     protected void processLogic() {

         locLat=application.getLatitude();
locLng=application.getLongitude(); FragmentManager manager = getSupportFragmentManager();
mapFragment = (SupportMapFragment) manager
.findFragmentById(R.direction_layout.map);
map = mapFragment.getMap();
initMap();
}

这里的3,4行为拿到当前本地的经纬度,application为一个Application类的对象,里面写有get方法,可以拿到当前本地经纬度。6,7行为得到mapFragment对象。9行为通过mapFragment获得GoogleMap对象,后面我们就是用这个map对象来画标记和线路。

     private void initMap() {
try {
//设置在地图上显示手机的位置,和显示控制按钮
map.setMyLocationEnabled(true);
//设置室内地图是否开启
map.setIndoorEnabled(true);
//设置地图类型三种:1:MAP_TYPE_NORMAL: Basic map with roads.
//2:MAP_TYPE_SATELLITE: Satellite view with roads.3:MAP_TYPE_TERRAIN: Terrain view without roads.
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// map.setTrafficEnabled(true);
map.setOnMapLongClickListener(onMapLongClickListener); GPSUtil gpsUtil = new GPSUtil();
gpsUtil.startLocation(this, getContentResolver(),
onLocationChangedListener); locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} catch (Exception e) {

}
}

这个方法用来初始化地图,3-11行为地图的设置,更多请查看:http://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html 。13-19行的GPSUtil为一个监听本地位置改变的类,当手机位置移动时GPS会得到移动后的经纬度。

     private OnLocationChangedListener onLocationChangedListener = new OnLocationChangedListener() {

         @Override
public void onLocationChanged(Location location) {
// To get the local latitude and longitude and set the map view to
// the position
if (location != null) {
locLat = location.getLatitude();
locLng = location.getLongitude();
locLatLng = new LatLng(locLat, locLng);
map.moveCamera(CameraUpdateFactory.newLatLng(locLatLng));
map.moveCamera(CameraUpdateFactory.zoomTo(15));
}
}
};

这个匿名类里的方法设置了当位置改变后地图上指示点和镜头的变化,拿到经纬度后用一个LatLng类的对象来存放,11,22行设置视角的移动,moveCamera方法传入的是一个CameraUpdate对象,该对象可用CameraUpdateFactory来生成,传入CameraUpdateFactory.newLatLng(locLatLng)移动到这个新的经纬度的位置,CameraUpdateFactory.zoomTo(15)设置移动后视角镜头大小。

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

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

     private OnFounedRoadRouteListener onFoundRoadRouteTaskListener = new OnFounedRoadRouteListener() {

         @SuppressWarnings("unchecked")
@Override
public void found(Object obj) {
if (obj != null) {
List<LatLng> tempLats = (List<LatLng>) obj;
latlngs.addAll(tempLats);
}
drawRoute();
}
};

从这个回调方法中得到处理好的LatLng对象,里面存放了用来画出线路的所有点的经纬度(把点连成线)。

     /**
* Draw route information
*/
private void drawRoute() {
try {
// Draw route info
map.addMarker(new MarkerOptions().position(latlngs.get(0)).title(address).visible(true));
PolylineOptions lineOptions = new PolylineOptions();
lineOptions.width(5);
for (int i = 0; i < latlngs.size() - 1; i++) {
lineOptions.add(latlngs.get(i));
}
map.addPolyline(lineOptions);
} catch (Exception e) {

}
}

这个方法就是画出线路的主要方法了,第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;
      /**
* Parses the returned lines of code of XML overview_polyline
*
* @return List<GeoPoint>
*/
private List<GeoPoint> decodePoly(String encoded) { 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) ((lat / 1E5) * 1E6),
(int) ((lng / 1E5) * 1E6));
poly.add(p);
} return poly;
}

这样返回的列表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. github/hexo搭建个人博客几个问题总结

    问题一:hexo ERROR Deployer not found: github or hexo ERROR Deployer not found: git npm install hexo-dep ...

  2. CF Two Buttons (BFS)

    Two Buttons time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  3. Socket编程初探

    一.什么是Socket? 通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.在Internet上的主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个S ...

  4. 使用C#动态生成Word文档/Excel文档的程序测试通过后,部署到IIS服务器上,不能正常使用的问题解决方案

    使用C#动态生成Word文档/Excel文档的程序功能调试.测试通过后,部署到服务器上,不能正常使用的问题解决方案: 原因: 可能asp.net程序或iis访问excel组件时权限不够(Ps:Syst ...

  5. mysql中文乱码的一点理解

    我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,总得知道个一二吧,不然以后如何优雅的吹牛B. 如果你也遇到了这个问题,咱 ...

  6. unity3d鼠标经过物体时变颜色,离开时恢复

    using UnityEngine; using System.Collections; public class MouseEvent_Color : MonoBehaviour { //物体初始颜 ...

  7. 你不知道的JSON的高效率用法

    1.JSON JSON是JavaScript Object Notation的缩写,是JavaScript标准的一个子集.官方Android API已经内置支持读写JSON数据.这种格式非常适合表示不 ...

  8. linux中sed用法

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为:         sed ...

  9. <Error>: CGContextRestoreGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

    转自这里   出 错原因:设置app的状态栏样式的使用使用了旧的方式,在info.plist里面设置了View controller- based status bar appearance为NO,默 ...

  10. html5笔记

    出处:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html HTML5 LocalStorage 本地存储 HTML5  ...