前一阵子我们物联网编程课老师要求班上每个人都要做一个地图应用,说是要利用起来安卓的GPS信息什么什么的……不过昨晚后觉得这根本就是在学Android开发嘛。。。
之前接触过一点安卓,也有JAVA基础,所以这次做东西还是比较快的,虽然已钱没有做过类似应用(其实都没有做过什么安卓应用),两天下来差不多把老师的要求都实现了,今天也顺利通过验收了。地图API我选的是百度的,支持国产~哈~全部的文件上传到附件了,有需要的同学可以下载~~
先看下Logo~哈~
按照百度地图开发者文档的指示一步一步做还是很顺利的~里面说的很清楚,我就直接贴代码了:
主界面
package com.micro.mymaps; import android.app.AlertDialog; import android.content.Intent; import android.location.Location; import android.os.Bundle; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.widget.Button; import android.widget.Toast; import android.widget.ToggleButton; import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.GeoPoint; import com.baidu.mapapi.LocationListener; import com.baidu.mapapi.MKLocationManager; import com.baidu.mapapi.MapActivity; import com.baidu.mapapi.MapController; import com.baidu.mapapi.MapView; import com.baidu.mapapi.MyLocationOverlay; public class MyMapActivity extends MapActivity { public static BMapManager mBMapMan = null; private MKLocationManager mLocationManager; private static MyLocationOverlay myLocationOverlay; private MapController mMapController; // 位置变化监听器 private MyLocationListener mllis; static MapView mMapView; // 卫星视图、交通视图按键 private ToggleButton WX_But, JT_But, FL_But; // 返回自己位置按键 private Button Return_But; // 按键监听器 private OnClickListener wx_but_lis; private OnClickListener jt_but_lis; private OnClickListener fl_but_lis; private OnClickListener Re_Lis; // 我的位置 protected static GeoPoint myLocation; // 地图是否随位置变化而变化 private boolean isFollow = false; // 是否是第一次定位 private boolean isFirst = true; // 退出事件监听器 private ExitButLinstener exitlis; // 标注点的数量 private int Pnum = 0; private boolean ceFlag = false; protected GeoPoint FirP; protected GeoPoint SecP; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * 初始化地图 */ mBMapMan = new BMapManager(getApplication()); mBMapMan.init("百度KEY", null);// KEY super.initMapActivity(mBMapMan); mMapView = (MapView) findViewById(R.id.bmapsView); // 初始化位置监听器 mllis = new MyLocationListener(); mLocationManager = mBMapMan.getLocationManager(); // 注册位置更新事件 mLocationManager.requestLocationUpdates(mllis); // 优先使用用GPS定位 mLocationManager .enableProvider((int) MKLocationManager.MK_GPS_PROVIDER); mLocationManager.setNotifyInternal(3, 1); // 优先使用网络来定位 // mLocationManager.enableProvider((int)MKLocationManager.MK_NETWORK_PROVIDER); // 添加定位图层 myLocationOverlay = new MyLocationOverlay(this, mMapView); // 注册GPS位置更新的事件,让地图能实时显示当前位置 myLocationOverlay.enableMyLocation(); // 开启磁场感应传感器 myLocationOverlay.enableCompass(); mMapView.getOverlays().add(myLocationOverlay); // 设置在缩放动画过程中也显示overlay,默认为不绘制 mMapView.setDrawOverlayWhenZooming(true);// 在缩放的时候显示覆盖物 mMapView.setBuiltInZoomControls(true); // 设置启用内置的缩放控件 mMapController = mMapView.getController(); // 得到mMapView的控制权,可以用它控制和驱动平移和缩放 // GeoPoint point = new GeoPoint((int) (39.915 * 1E6), // (int) (116.404 * 1E6)); // 用给定的经纬度构造一个GeoPoint,单位是微度 (度 * 1E6) 天,安。门坐标 mMapController.setZoom(12); // 设置地图zoom级别 mMapView.setSatellite(false);// 设置卫星视图 mMapView.setTraffic(false);// 设置交通状况视图 // mMapView.getOverlays().add(new MyOverlay());// 在地图上添加自己设置的覆盖物 // 初始化按键及监听器 WX_But = (ToggleButton) findViewById(R.id.WX_But); JT_But = (ToggleButton) findViewById(R.id.JT_But); FL_But = (ToggleButton) findViewById(R.id.FL_But); Return_But = (Button) findViewById(R.id.ReturnMyPlace); // 卫星视图按键监听器 wx_but_lis = new OnClickListener() { public void onClick(View v) { if (WX_But.isChecked()) { mMapView.setSatellite(true); } else { mMapView.setSatellite(false); } } }; WX_But.setOnClickListener(wx_but_lis); // 交通视图按键监听器 jt_but_lis = new OnClickListener() { public void onClick(View v) { if (JT_But.isChecked()) { mMapView.setTraffic(true); } else { mMapView.setTraffic(false); } } }; JT_But.setOnClickListener(jt_but_lis); // 地图跟随按键监听器 fl_but_lis = new OnClickListener() { public void onClick(View v) { if (JT_But.isChecked()) { isFollow = true; } else { isFollow = false; } } }; FL_But.setOnClickListener(fl_but_lis); // 返回我的位置按钮监听器 Re_Lis = new OnClickListener() { public void onClick(View v) { if (myLocation == null) { DisplayToast("暂未获取到位置信息~"); } else { mMapController.setZoom(15); mMapController.animateTo(myLocation); // 设置地图中心点 } } }; Return_But.setOnClickListener(Re_Lis); exitlis = new ExitButLinstener(); mMapView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub if (ceFlag) if (event.getAction() == MotionEvent.ACTION_DOWN) { if (Pnum == 0) { System.out.println("第一次"); FirP = mMapView.getProjection().fromPixels( (int) event.getX(), (int) event.getY()); mMapView.getOverlays().add(new PointOverLay(FirP)); Pnum++; } else if (Pnum == 1) { System.out.println("第二次"); SecP = mMapView.getProjection().fromPixels( (int) event.getX(), (int) event.getY()); mMapView.getOverlays().add(new PointOverLay(SecP)); mMapView.getOverlays().add( new LineOverLay(FirP, SecP)); Distence dis = new Distence(); double dist = dis.GetShortDistance( FirP.getLongitudeE6(), FirP.getLatitudeE6(), SecP.getLongitudeE6(), SecP.getLatitudeE6()); DisplayToast("距离为" + ((int) dist / 1000000) + "米"); Pnum++; } else { DisplayToast("请清空后继续测量"); } } return false; } }); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } @Override protected void onDestroy() { if (mBMapMan != null) { mBMapMan.destroy(); mBMapMan = null; } super.onDestroy(); } @Override protected void onPause() { if (mBMapMan != null) { // 移除listener mBMapMan.getLocationManager().removeUpdates(mllis); mBMapMan.stop(); } super.onPause(); } @Override protected void onResume() { if (mBMapMan != null) { // 注册Listener mBMapMan.getLocationManager().requestLocationUpdates(mllis); mBMapMan.start(); } super.onResume(); } /** * 根据MyLocationOverlay配置的属性确定是否在地图上显示当前位置 */ @Override protected boolean isLocationDisplayed() { return myLocationOverlay.isMyLocationEnabled(); } // @Override // public boolean onCreateOptionsMenu(Menu menu) { // // 调用父类方法来加入系统菜单 // // 虽然目前android还没有系统菜单,但是为了兼容到以后的版本,最好加上 // super.onCreateOptionsMenu(menu); // // // 添加菜单项(多种方式) // // 1.直接指定标题 // menu.add("菜单项1"); // // 2.通过资源指定标题 // menu.add(R.string.jiaotong); // // 3.显示指定菜单项的组号、ID、排序号、标题 // menu.add(1, // 组号 // Menu.FIRST, // 唯一的ID号 // Menu.FIRST, // 排序号 // "菜单项3"); // 标题 // // // 如果希望显示菜单,请返回true // return true; // } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // 添加4个菜单项,分成2组 int group1 = 1; int gourp2 = 2; int gourp3 = 3; menu.add(group1, 1, 1, "地图查询"); menu.add(group1, 2, 2, "线路搜索"); menu.add(gourp2, 3, 3, "距离测量"); menu.add(gourp2, 4, 4, "地图复位"); menu.add(gourp3, 5, 5, "关于软件"); menu.add(gourp3, 6, 6, "退出应用"); // 显示菜单 return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent intent = null; switch (item.getItemId()) { // 响应每个菜单项(通过菜单项的ID) case 1: // do something here // DisplayToast("地图查询"); intent = null; intent = new Intent(MyMapActivity.this, SearchActivity.class); this.startActivity(intent); break; case 2: // do something here // DisplayToast("线路搜索"); intent = null; intent = new Intent(MyMapActivity.this, RoutePlan.class); this.startActivity(intent); break; case 3: // do something here // DisplayToast("距离测量"); clearMap(); Pnum = 0; ceFlag = true; break; case 4: // do something here DisplayToast("地图复位"); clearMap(); JT_But.setChecked(false); mMapView.setTraffic(false); WX_But.setChecked(false); mMapView.setSatellite(false); FL_But.setChecked(false); isFollow = false; mMapController.setZoom(15); if (myLocation != null) mMapController.animateTo(myLocation); Pnum = 0; ceFlag = false; break; case 5: // do something here DisplayToast("关于软件"); new AlertDialog.Builder(this).setTitle("关于软件") .setMessage("制作:中南大学——李众力\n谢谢使用本软件~O(∩_∩)O~") .setPositiveButton("确定", null).show(); break; case 6: // do something here // DisplayToast("退出应用"); new AlertDialog.Builder(this).setTitle("确认退出") .setMessage("是否退出本应用?").setPositiveButton("是", exitlis) .setNegativeButton("否", null).show(); break; default: // 对没有处理的事件,交给父类来处理 return super.onOptionsItemSelected(item); } // 返回true表示处理完菜单项的事件,不需要将该事件继续传播下去了 return true; } // 显示提示 public void DisplayToast(String str) { Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); } // 将当前位置转换成地理坐标点 public GeoPoint Lo2Gp(Location location) { if (location == null) return null; return new GeoPoint((int) (location.getLatitude() * 1000000), (int) (location.getLongitude() * 1000000)); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_BACK: AlertDialog.Builder build = new AlertDialog.Builder(this); build.setTitle("注意").setMessage("确定要退出吗?") .setPositiveButton("确定", exitlis) .setNegativeButton("取消", null).show(); break; default: break; } return false; // return super.onKeyDown(keyCode, event); } // 清除多余overlay方法 public static void clearMap() { mMapView.getOverlays().clear(); mMapView.getOverlays().add(myLocationOverlay); } /** * 内部类,实现位置变化监听 * * @author Micro * */ class MyLocationListener implements LocationListener { /** * 位置变化监听器 */ public void onLocationChanged(Location location) { System.out.println("位置变化!\n"); if (location != null) { // 将当前位置转换成地理坐标点 final GeoPoint pt = new GeoPoint( (int) (location.getLatitude() * 1000000), (int) (location.getLongitude() * 1000000)); myLocation = pt; if (isFirst) { mMapController.setZoom(15); mMapController.animateTo(myLocation); isFirst = false; } if (isFollow) { mMapController.animateTo(myLocation); } } } } }
界面的xml文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <com.baidu.mapapi.MapView android:id="@+id/bmapsView" android:layout_width="fill_parent" android:layout_height="400dp" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:clickable="true" > </com.baidu.mapapi.MapView> <Button android:id="@+id/ReturnMyPlace" style="?android:attr/buttonStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:text="@string/returnMyP" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <ToggleButton android:id="@+id/JT_But" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="30dp" android:textOff="@string/jiaotong" android:textOn="@string/jiaotong" /> <ToggleButton android:id="@+id/WX_But" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/JT_But" android:layout_alignBottom="@+id/JT_But" android:layout_centerHorizontal="true" android:textOff="@string/weixing" android:textOn="@string/weixing" /> <ToggleButton android:id="@+id/FL_But" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/WX_But" android:layout_alignBottom="@+id/WX_But" android:layout_marginLeft="28dp" android:layout_toRightOf="@+id/WX_But" android:textOff="@string/Follow" android:textOn="@string/Follow" /> </RelativeLayout> </LinearLayout>
因为响应按钮操作的OnClickLinstener和View里面的方法名字一样,我救另外建了一个类来实现监听方法:
退出按钮:
package com.micro.mymaps; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; public class ExitButLinstener implements OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { System.exit(0); } }
搜索界面:我把MapView设置为了静态的全局变量,搜索结果显示在主界面上,另外设这个这个界面是透明的,这样看起来就像是之前被隐藏起来了一样,另外这个界面是通过百度提供的Demo修改来的,其中有个Suggestion的方法我没有用到,但是也没删除,而是在界面的XML文件里把相应的组件隐藏起来了,这样一后可以接着学~
java文件:
package com.micro.mymaps; import com.baidu.mapapi.MKAddrInfo; import com.baidu.mapapi.MKBusLineResult; import com.baidu.mapapi.MKDrivingRouteResult; import com.baidu.mapapi.MKPoiResult; import com.baidu.mapapi.MKSearch; import com.baidu.mapapi.MKSearchListener; import com.baidu.mapapi.MKSuggestionResult; import com.baidu.mapapi.MKTransitRouteResult; import com.baidu.mapapi.MKWalkingRouteResult; import com.baidu.mapapi.PoiOverlay; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; public class SearchActivity extends Activity { Button mBtnSearch = null; // 搜索按钮 Button mSuggestionSearch = null; // suggestion搜索 ListView mSuggestionList = null; public static String mStrSuggestions[] = {}; MKSearch mSearch = null; // 搜索模块,也可去掉地图模块独立使用 protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.searchact); // 初始化搜索模块,注册事件监听 mSearch = new MKSearch(); mSearch.init(MyMapActivity.mBMapMan, new MKSearchListener() { public void onGetPoiResult(MKPoiResult res, int type, int error) { // 错误号可参考MKEvent中的定义 if (error != 0 || res == null) { Toast.makeText(SearchActivity.this, "抱歉,未找到结果", Toast.LENGTH_LONG).show(); return; } // 将地图移动到第一个POI中心点 if (res.getCurrentNumPois() > 0) { // 将poi结果显示到地图上 PoiOverlay poiOverlay = new PoiOverlay(SearchActivity.this, MyMapActivity.mMapView); poiOverlay.setData(res.getAllPoi()); MyMapActivity.clearMap(); MyMapActivity.mMapView.getOverlays().add(poiOverlay); MyMapActivity.mMapView.invalidate(); MyMapActivity.mMapView.getController().setCenter( res.getPoi(0).pt); closeit(); } else if (res.getCityListNum() > 0) { String strInfo = "在"; for (int i = 0; i < res.getCityListNum(); i++) { strInfo += res.getCityListInfo(i).city; strInfo += ","; } strInfo += "找到结果"; Toast.makeText(SearchActivity.this, strInfo, Toast.LENGTH_LONG).show(); } } public void onGetDrivingRouteResult(MKDrivingRouteResult res, int error) { } public void onGetTransitRouteResult(MKTransitRouteResult res, int error) { } public void onGetWalkingRouteResult(MKWalkingRouteResult res, int error) { } public void onGetAddrResult(MKAddrInfo res, int error) { } public void onGetBusDetailResult(MKBusLineResult result, int iError) { } public void onGetSuggestionResult(MKSuggestionResult res, int arg1) { // TODO Auto-generated method stub if (arg1 != 0 || res == null) { Toast.makeText(SearchActivity.this, "抱歉,未找到结果", Toast.LENGTH_LONG).show(); return; } int nSize = res.getSuggestionNum(); mStrSuggestions = new String[nSize]; for (int i = 0; i < nSize; i++) { mStrSuggestions[i] = res.getSuggestion(i).city + res.getSuggestion(i).key; } ArrayAdapter<String> suggestionString = new ArrayAdapter<String>( SearchActivity.this, android.R.layout.simple_list_item_1, mStrSuggestions); mSuggestionList.setAdapter(suggestionString); Toast.makeText(SearchActivity.this, "suggestion callback", Toast.LENGTH_LONG).show(); } }); mSuggestionList = (ListView) findViewById(R.id.listView1); // 设定搜索按钮的响应 mBtnSearch = (Button) findViewById(R.id.search); OnClickListener clickListener = new OnClickListener() { public void onClick(View v) { SearchButtonProcess(v); } }; mBtnSearch.setOnClickListener(clickListener); // 设定suggestion响应 mSuggestionSearch = (Button) findViewById(R.id.suggestionsearch); OnClickListener clickListener1 = new OnClickListener() { public void onClick(View v) { SuggestionSearchButtonProcess(v); } }; mSuggestionSearch.setOnClickListener(clickListener1); } void SearchButtonProcess(View v) { if (mBtnSearch.equals(v)) { // Intent intent = null; // intent = new Intent(SearchActivity.this, MyMapActivity.class); // this.startActivity(intent); EditText editCity = (EditText) findViewById(R.id.city); EditText editSearchKey = (EditText) findViewById(R.id.searchkey); mSearch.poiSearchInCity(editCity.getText().toString(), editSearchKey.getText().toString()); } } void SuggestionSearchButtonProcess(View v) { EditText editSearchKey = (EditText) findViewById(R.id.suggestionkey); mSearch.suggestionSearch(editSearchKey.getText().toString()); } private void closeit() { this.finish(); } @Override protected void onPause() { MyMapActivity.mBMapMan.stop(); super.onPause(); } @Override protected void onResume() { MyMapActivity.mBMapMan.start(); super.onResume(); } }
地图查询XML文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:visibility="visible" tools:ignore="HardcodedText,TextFields" > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/translucent_background" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="在" > </TextView> <EditText android:id="@+id/city" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="北京" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="市内找" > </TextView> <EditText android:id="@+id/searchkey" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清华大学" /> <Button android:id="@+id/search" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="搜索" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@color/translucent_background" android:orientation="horizontal" android:visibility="invisible" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关键词" > </TextView> <EditText android:id="@+id/suggestionkey" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清华大学" /> <Button android:id="@+id/suggestionsearch" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="关键词搜索" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/translucent_background" android:visibility="invisible" > </ListView> </LinearLayout> </LinearLayout>
下面是路线规划界面,也是直接从百度提供的Demo修改而来,这个功能有缺陷,比如说当起点和终点名称有歧义的时候就不能返回查询线路信息,但是由于时间比较紧,我救只把界面写出来了,相应的功能还没实现,接下来再做吧。
java代码:
package com.micro.mymaps; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import com.baidu.mapapi.MKAddrInfo; import com.baidu.mapapi.MKBusLineResult; import com.baidu.mapapi.MKDrivingRouteResult; import com.baidu.mapapi.MKGeocoderAddressComponent; import com.baidu.mapapi.MKPlanNode; import com.baidu.mapapi.MKPoiResult; import com.baidu.mapapi.MKSearch; import com.baidu.mapapi.MKSearchListener; import com.baidu.mapapi.MKSuggestionResult; import com.baidu.mapapi.MKTransitRouteResult; import com.baidu.mapapi.MKWalkingRouteResult; import com.baidu.mapapi.MapActivity; import com.baidu.mapapi.RouteOverlay; import com.baidu.mapapi.TransitOverlay; public class RoutePlan extends MapActivity { private Button mBtnDrive = null; // 驾车搜索 private Button mBtnTransit = null; // 公交搜索 private Button mBtnWalk = null; // 步行搜索 private MKSearch mSearch = null; // 搜索模块,也可去掉地图模块独立使用 private static String MyCity = "长沙市";// 默认为长沙市 private EditText editSt;// 输入起点的输入框 private EditText editEn;// 输入终点的输入框 Button ckStr;// 确认起点按钮 Button ckEnd;// 确认起点按钮 ListView list;// 如果结果不唯一,显示结果 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.routeplan); // 初始化搜索模块,注册事件监听 mSearch = new MKSearch(); mSearch.init(MyMapActivity.mBMapMan, new MKSearchListener() { public void onGetDrivingRouteResult(MKDrivingRouteResult res, int error) { // 错误号可参考MKEvent中的定义 if (error != 0 || res == null) { // if (error == 4/* 线路起点终点有歧义 */) { // Toast.makeText(RoutePlan.this, "线路起点终点有歧义", // Toast.LENGTH_SHORT).show(); // } // if (res == null) Toast.makeText(RoutePlan.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); return; } RouteOverlay routeOverlay = new RouteOverlay(RoutePlan.this, MyMapActivity.mMapView); // 此处仅展示一个方案作为示例 routeOverlay.setData(res.getPlan(0).getRoute(0)); MyMapActivity.clearMap(); MyMapActivity.mMapView.getOverlays().add(routeOverlay); MyMapActivity.mMapView.invalidate(); MyMapActivity.mMapView.getController().animateTo( res.getStart().pt); } public void onGetTransitRouteResult(MKTransitRouteResult res, int error) { if (error != 0 || res == null) { // if (error == 4/* 线路起点终点有歧义 */) { // Toast.makeText(RoutePlan.this, "线路起点终点有歧义", // Toast.LENGTH_SHORT).show(); // } // if (res == null) Toast.makeText(RoutePlan.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); return; } TransitOverlay routeOverlay = new TransitOverlay( RoutePlan.this, MyMapActivity.mMapView); // 此处仅展示一个方案作为示例 routeOverlay.setData(res.getPlan(0)); MyMapActivity.clearMap(); MyMapActivity.mMapView.getOverlays().add(routeOverlay); MyMapActivity.mMapView.invalidate(); MyMapActivity.mMapView.getController().animateTo( res.getStart().pt); } public void onGetWalkingRouteResult(MKWalkingRouteResult res, int error) { if (error != 0 || res == null) { // if (error == 4/* 线路起点终点有歧义 */) { // Toast.makeText(RoutePlan.this, "线路起点终点有歧义", // Toast.LENGTH_SHORT).show(); // } // if (res == null) Toast.makeText(RoutePlan.this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); return; } RouteOverlay routeOverlay = new RouteOverlay(RoutePlan.this, MyMapActivity.mMapView); // 此处仅展示一个方案作为示例 routeOverlay.setData(res.getPlan(0).getRoute(0)); MyMapActivity.clearMap(); MyMapActivity.mMapView.getOverlays().add(routeOverlay); MyMapActivity.mMapView.invalidate(); MyMapActivity.mMapView.getController().animateTo( res.getStart().pt); } public void onGetAddrResult(MKAddrInfo res, int error) { MKGeocoderAddressComponent kk = res.addressComponents; MyCity = kk.city; Toast.makeText(RoutePlan.this, "所在城市:" + MyCity, Toast.LENGTH_SHORT).show(); } public void onGetPoiResult(MKPoiResult res, int arg1, int arg2) { } public void onGetBusDetailResult(MKBusLineResult result, int iError) { } public void onGetSuggestionResult(MKSuggestionResult res, int arg1) { // TODO Auto-generated method stub } }); // 查询当先所在城市 mSearch.reverseGeocode(MyMapActivity.myLocation); // 设定搜索按钮的响应 mBtnDrive = (Button) findViewById(R.id.drive); mBtnTransit = (Button) findViewById(R.id.transit); mBtnWalk = (Button) findViewById(R.id.walk); OnClickListener clickListener = new OnClickListener() { public void onClick(View v) { SearchButtonProcess(v); } }; mBtnDrive.setOnClickListener(clickListener); mBtnTransit.setOnClickListener(clickListener); mBtnWalk.setOnClickListener(clickListener); ckStr = (Button) findViewById(R.id.strCon); ckEnd = (Button) findViewById(R.id.endCon); list = (ListView) findViewById(R.id.listView1); // 处理搜索按钮响应 editSt = (EditText) findViewById(R.id.start); editEn = (EditText) findViewById(R.id.end); } private void SearchButtonProcess(View v) { // 对起点终点的name进行赋值,也可以直接对坐标赋值,赋值坐标则将根据坐标进行搜索 MKPlanNode stNode = new MKPlanNode(); String stName = editSt.getText().toString(); if (stName.equals("")) { if (MyMapActivity.myLocation == null) { Toast.makeText(RoutePlan.this, "暂未获取到位置信息~", Toast.LENGTH_SHORT) .show(); return; } stNode.pt = MyMapActivity.myLocation; Toast.makeText(RoutePlan.this, "以自身作为起点", Toast.LENGTH_SHORT) .show(); } else { stNode.name = stName; } String enName = editEn.getText().toString(); if (enName.equals("")) { Toast.makeText(RoutePlan.this, "请输入目的地", Toast.LENGTH_SHORT).show(); return; } MKPlanNode enNode = new MKPlanNode(); enNode.name = enName; // 实际使用中请对起点终点城市进行正确的设定 if (mBtnDrive.equals(v)) { mSearch.drivingSearch(MyCity, stNode, MyCity, enNode); } else if (mBtnTransit.equals(v)) { mSearch.transitSearch(MyCity, stNode, enNode); } else if (mBtnWalk.equals(v)) { mSearch.walkingSearch(MyCity, stNode, MyCity, enNode); } Toast.makeText(RoutePlan.this, MyCity + "从" + editSt.getText() + "到" + editEn.getText(), Toast.LENGTH_SHORT).show(); } @Override protected void onPause() { MyMapActivity.mBMapMan.stop(); super.onPause(); } @Override protected void onResume() { MyMapActivity.mBMapMan.start(); super.onResume(); } @Override protected boolean isRouteDisplayed() { // TODO Auto-generated method stub return false; } /** * 查询起点和终点,确定线路起终点唯一 */ class CkStrListener implements OnClickListener { @Override public void onClick(View v) { Button but = (Button) v; if (but.getText().equals("确认起点")) { } } } }
路线规划XML文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" tools:ignore="TextFields,HardcodedText" > <LinearLayout android:id="@+id/LinearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/translucent_background" > <TableRow android:id="@+id/tableRow1" android:layout_width="wrap_content" android:layout_height="match_parent" > </TableRow> <EditText android:id="@+id/start" android:layout_width="240dp" android:layout_height="wrap_content" android:ems="10" android:hint="起点(默认为用户当前位置)" tools:ignore="HardcodedText" > <requestFocus /> </EditText> <Button android:id="@+id/strCon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确认起点" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/translucent_background" > <EditText android:id="@+id/end" android:layout_width="240dp" android:layout_height="match_parent" android:ems="10" android:hint="终点" tools:ignore="HardcodedText" /> <Button android:id="@+id/endCon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确认终点" /> </LinearLayout> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/translucent_background" android:orientation="horizontal" > <Button android:id="@+id/drive" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="驾车搜索" /> <Button android:id="@+id/transit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="公交搜索" /> <Button android:id="@+id/walk" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="步行搜索" /> </LinearLayout> <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/translucent_background" > </ListView> </LinearLayout>
最后一个功能就是测距,百度也提供了示例代码:
package com.micro.mymaps; public class Distence { static double DEF_PI = 3.14159265359; // PI static double DEF_2PI = 6.28318530712; // 2*PI static double DEF_PI180 = 0.01745329252; // PI/180.0 static double DEF_R = 6370693.5; // radius of earth public double GetShortDistance(double lon1, double lat1, double lon2, double lat2) { double ew1, ns1, ew2, ns2; double dx, dy, dew; double distance; // 角度转换为弧度 ew1 = lon1 * DEF_PI180; ns1 = lat1 * DEF_PI180; ew2 = lon2 * DEF_PI180; ns2 = lat2 * DEF_PI180; // 经度差 dew = ew1 - ew2; // 若跨东经和西经180 度,进行调整 if (dew > DEF_PI) dew = DEF_2PI - dew; else if (dew < -DEF_PI) dew = DEF_2PI + dew; dx = DEF_R * Math.cos(ns1) * dew; // 东西方向长度(在纬度圈上的投影长度) dy = DEF_R * (ns1 - ns2); // 南北方向长度(在经度圈上的投影长度) // 勾股定理求斜边长 distance = Math.sqrt(dx * dx + dy * dy); return distance; } public double GetLongDistance(double lon1, double lat1, double lon2, double lat2) { double ew1, ns1, ew2, ns2; double distance; // 角度转换为弧度 ew1 = lon1 * DEF_PI180; ns1 = lat1 * DEF_PI180; ew2 = lon2 * DEF_PI180; ns2 = lat2 * DEF_PI180; // 求大圆劣弧与球心所夹的角(弧度) distance = Math.sin(ns1) * Math.sin(ns2) + Math.cos(ns1) * Math.cos(ns2) * Math.cos(ew1 - ew2); // 调整到[-1..1]范围内,避免溢出 if (distance > 1.0) distance = 1.0; else if (distance < -1.0) distance = -1.0; // 求大圆劣弧长度 distance = DEF_R * Math.acos(distance); return distance; } double mLat1 = 39.90923; // point1纬度 double mLon1 = 116.357428; // point1经度 double mLat2 = 39.90923;// point2纬度 double mLon2 = 116.397428;// point2经度 double distance = GetShortDistance(mLon1, mLat1, mLon2, mLat2); }
然后在主界面设置一个标志变量,当选择测量距离的时候监听触摸屏幕事件,当第一次触摸的时候画一个五角星并记录该点的地理坐标,第二次触摸则画一条线加一个五角星,并计算两点间的距离,现在计算出来的距离貌似偏差有点大,可能是数据处理的不对吧。下面是自己重写的两个Overlay:
package com.micro.mymaps; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import com.baidu.mapapi.GeoPoint; import com.baidu.mapapi.MapView; import com.baidu.mapapi.Overlay; public class PointOverLay extends Overlay { GeoPoint geoPoint; Paint paint = new Paint(); public PointOverLay(GeoPoint geoPoint){ this.geoPoint=geoPoint; } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { Point point = mapView.getProjection().toPixels(geoPoint, null); canvas.drawText("★", point.x, point.y, paint); } }
package com.micro.mymaps;
import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import com.baidu.mapapi.GeoPoint; import com.baidu.mapapi.MapView; import com.baidu.mapapi.Overlay; public class LineOverLay extends Overlay { GeoPoint geoPoint1; GeoPoint geoPoint2; Paint paint = new Paint(); public LineOverLay(GeoPoint geoPoint1, GeoPoint geoPoint2) { this.geoPoint1 = geoPoint1; this.geoPoint2 = geoPoint2; } @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { Point point1 = mapView.getProjection().toPixels(geoPoint1, null); Point point2 = mapView.getProjection().toPixels(geoPoint2, null); canvas.drawLine(point1.x, point1.y, point2.x, point2.y, paint); } }
两天时间几乎都在搞这个,感觉利用API做程序还是挺简单的,就是写界面什么的比较麻烦,主要还是要加上自己的创意吧~