在这篇里我们只聊怎么在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. CF Vitaly and Strings

    Vitaly and Strings time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  2. 关于Eclipse中Browser中显示html页面的总结.

    用Eclipse中的Browser显示html页面,因为"just small thing.. browser in the studio is light browser.. it can ...

  3. 用java调用oracle存储过程总结(转)

    //1.call+包名+存储过程名(传入.传出值用?) String str="{call SMSBUSINESS.deleteZhZMember(?,?,?)}"; //2.建立 ...

  4. Ehcache(2.9.x) - API Developer Guide, Key Classes and Methods

    About the Key Classes Ehcache consists of a CacheManager, which manages logical data sets represente ...

  5. 【ANT】构建文件build.xml

    运行ant: ant 使用当前目录下的build.xml运行ant,指定缺省的target; ant –buildfile mybuild.xml 使用当前目录下的mybuild.xml运行ant,并 ...

  6. AngularJS Tabular Data with Edit/Update/Delete

    效果 首先,我们先建立一些数据,当然你可以从你任何地方读出你的数据 var app = angular.module('plunker', ['ui.bootstrap']); app.control ...

  7. C# 网页信息采集(数据访问)

    windows nt/xp/2003 or above .net Framework 1.1 SqlServer 2000 开发环境 VS 2003 目的 学习了网络编程,总要做点什么东西才好. 于是 ...

  8. win7 服务详解-系统优化

    Adaptive Brightness监视氛围光传感器,以检测氛围光的变化并调节显示器的亮度.如果此服务停止或被禁用,显示器亮度将不根据照明条件进行调节.该服务的默认运行方式是手动,如果你没有使用触摸 ...

  9. 初话C++模板【用自己的话,解释清楚这些】

    用自己的话解释清楚C++的模板编程 模板编程是为了解决什么问题而出现的? 提高代码的重用性,提高代码的利用率. 泛型编程的一种实现. 模板的精神是: 类型参数化. 模板的实现 模板分为:函数模板.类模 ...

  10. struts2文件上传(保存为BLOB格式)

    html文件:提供上传文件的入口 <input type="file" name="upload"><!-- name很重要,与后面actio ...