在这篇里我们只聊怎么在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. 【Stirling Number I】

    hdu 4372 Count the Buildings 推荐这位小哥的,我觉得人家说的灰常的好. 注意数据范围,n,f,b均在(0,2000]范围内,而第一斯特林数的数组范围却是s[2000+5][ ...

  2. 软件设计师考试计算机系统知识——CPU

    第一章: 计算机系统知识 1.1.1计算机系统硬件的基本组成 运算器.控制器.存储器.输入设备.输出设备 1.1.2 中央处理器 ①CPU的功能: a.程序控制:CPU通过执行指令来控制程序执行的顺序 ...

  3. JMS - Message

    一条 JMS 消息包含三个部分:消息头.消息属性和消息体. 消息头 消息头提供了和消息有关的元数据,它描述了消息有谁创建.何时创建.数据的有效长度等信息.消息头还包含了描述消息目的地(主题或队列)的路 ...

  4. C++ Iterator迭代器介绍及Iterator迭代器用法代码举例

    C++ Iterator迭代器介绍 迭代器可被用来访问一个容器类的所包函的全部元素,其行为像一个指针.举一个例子,你可用一个迭代器来实现对vector容器中所含元素的遍历.有这么几种迭代器如下: 迭代 ...

  5. Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法(转)

    本篇文章,介绍Microsoft Dynamics CRM 2011的组织服务中的RetrieveMultiple方法. RetreiveMultiple方法,用于获取实体的多个实例,该方法的签名如下 ...

  6. 使用JS调用WebService接口

    <script> $(document).ready(function () { var username = "admin"; var password = &quo ...

  7. 在ASP.NET中实现压缩多个文件为.zip文件,实现批量下载功能 (转载并优化处理篇)

    转自:http://blog.csdn.net/yanlele424/article/details/6895986 这段时间一直在做一个网站,其中遇到了一个问题,就是在服务器端压缩多个服务器端的文件 ...

  8. js中元素操作的有关内容与对比

    以下 A:代表原生js B:代表jQuery 1 创建元素/节点 A: 元素节点- createElement( ) 文本节点 - createTextNode() 例如: var a = docum ...

  9. [SWF]在线预览文档下载

    写本文的缘由:领导有些项目文档需要审阅,网站上的文档只能在线预览,没有提供下载.开始用截屏的方式,可想而知这将会是多大的重复性劳动.所以研究了一下,发现可以曲线救国,所以在这里分享一下. 问题描述:这 ...

  10. ZStack中的编程技巧

    1. 像函数一样使用的宏 //这个宏,用来被其他宏使用,构造一个正确有效的表达式.这个适合于一些离散语句的组合,不适合函数的重新命名 #define st(x)      do { x } while ...