近由于项目需要,研究了下百度地图定位,他们提供的实例基本都是用监听器实现自动定位的。我想实现一种效果:当用户进入UI时,不定位,用户需要定位的时候,自己手动点击按钮,再去定位当前位置。
经过2天研究和咨询,找到了解决方案,在此备忘一下。
注意:定位使用真机才能够真正定位;模拟器的话,在DDMS中的Emulator
Control中,选择Manual,下面单选按钮选择Decimal,然后填写经纬度,send后,再点击定位我的位置按钮,就能定位了(这应该算是固定定位,哈哈。。。)、
1、第一步当然是获取一个针对自己项目的key值。http://dev.baidu.com/wiki/static/imap/key/
2、使用百度API是有前提的,摘自百度:首先将API包括的两个文件baidumapapi.jar和
libBMapApiEngine.so拷贝到工程根目录及libs\armeabi目录下,并在工程属性->Java Build
Path->Libraries中选择“Add
JARs”,选定baidumapapi.jar,确定后返回,这样您就可以在您的程序中使用API了。(这两个文件见附件)。
3、按照自己的需求写一个layout,我的如下:
<?xml version="1.0" encoding="utf-8"?>
Xml代码
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <TextView
- android:id="@+id/myLocation_id"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:textSize="15dp"
- android:gravity="center_horizontal"
- android:textColor="@drawable/black"
- android:background="@drawable/gary"
- />
- <com.baidu.mapapi.MapView android:id="@+id/bmapsView"
- android:layout_width="fill_parent"
android:layout_height="fill_parent" - android:clickable="true"
android:layout_weight="1" - />
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/location_button_id"
- android:text="@string/location_button_text"
- />
- </LinearLayout>
需要特别注意的是:<com.baidu.mapapi.MapView /> 这玩意。
4、写一个MapApplication实现application,提供全局的BMapManager,以及其初始化。
Java代码
- public BMapManager mapManager = null;
- static MapApplication app;
- public String mStrKey = "你申请的key值";
- @Override
- public void onCreate() {
- mapManager = new BMapManager(this);
- mapManager.init(mStrKey, new
MyGeneralListener()); - }
- @Override
- //建议在您app的退出之前调用mapadpi的destroy()函数,避免重复初始化带来的时间消耗
- public void onTerminate() {
- // TODO Auto-generated method stub
- if(mapManager != null)
- {
- mapManager.destroy();
- mapManager = null;
- }
- super.onTerminate();
- }
- static class MyGeneralListener implements MKGeneralListener{
- @Override
- public void onGetNetworkState(int arg0) {
- Toast.makeText(MapApplication.app.getApplicationContext(),
"您的网络出错啦!", - Toast.LENGTH_LONG).show();
- }
- @Override
- public void onGetPermissionState(int iError) {
- if (iError ==
MKEvent.ERROR_PERMISSION_DENIED) { - //
授权Key错误: - Toast.makeText(MapApplication.app.getApplicationContext(),"您的授权Key不正确!",
- Toast.LENGTH_LONG).show();
- }
- }
- }
- 5、接下来就是按照百度api写定位代码了,使用handler机制去添加定位图层,需要说明的都在注释上了。
- private BMapManager mBMapMan =
null; - private MapView mMapView = null;
- private MapController bMapController;
- private MKLocationManager mkLocationManager;
- private MKSearch mkSearch;
- private TextView address_view; //定位到的位置信息
- private ProgressDialog dialog;
- private List<HotelInfo> hotelList;
- private int distance = 1000; //查询的范围(单位:m)
- Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- double lat =
msg.getData().getDouble("lat"); - double lon =
msg.getData().getDouble("lon"); - if(lat!=0&&lon!=0){
- GeoPoint
point = new GeoPoint( - (int) (lat * 1E6),
- (int) (lon * 1E6));
- bMapController.animateTo(point); //设置地图中心点
- bMapController.setZoom(15);
- mkSearch.reverseGeocode(point); //解析地址(异步方法)
- MyLocationOverlay myLoc = new
MyLocationOverlayFromMap(ShowMapAct.this,mMapView); - myLoc.enableMyLocation(); // 启用定位
- myLoc.enableCompass(); // 启用指南针
- mMapView.getOverlays().add(myLoc);
- }else{
- Toast.makeText(ShowMapAct.this, "没有加载到您的位置",
Toast.LENGTH_LONG).show(); - }
- if(hotelList!=null){
- Drawable
marker = getResources().getDrawable(R.drawable.iconmarka);
//设置marker - marker.setBounds(0, 0, marker.getIntrinsicWidth(),
marker.getIntrinsicHeight()); //为maker定义位置和边界 - mMapView.getOverlays().add(new
OverItemList(marker,hotelList,ShowMapAct.this,bMapController)); - }else
if(hotelList==null&&lat!=0&&lon!=0){ - Toast.makeText(ShowMapAct.this, "网络异常,没有获取到酒店信息。",
Toast.LENGTH_LONG).show(); - }
- if(dialog!=null)
dialog.dismiss(); - }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- distance =
getIntent().getExtras().getInt("distance"); //获取查询范围 - super.onCreate(savedInstanceState);
- setContentView(R.layout.location);
- mMapView =
(MapView)findViewById(R.id.bmapsView); //初始化一个mapView
存放Map - init(); //初始化地图管理器
- super.initMapActivity(mBMapMan);
- address_view =
(TextView)findViewById(R.id.myLocation_id); - SpannableStringBuilder style = new
SpannableStringBuilder(String.format(getResources().getString(R.string.location_text),"位置不详")); - style.setSpan(new ForegroundColorSpan(Color.RED), 5,
style.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - address_view.setText(style);
- Button location_button =
(Button)findViewById(R.id.location_button_id); - location_button.setOnClickListener(new
View.OnClickListener(){ - @Override
- public void onClick(View v)
{ - dialog = ProgressDialog.show(ShowMapAct.this, "", "数据加载中,请稍后.....");
- new Thread(new MyThread()).start();
- }
- });
- mkSearch = new MKSearch();
//初始化一个MKSearch,根据location解析详细地址 - mkSearch.init(mBMapMan, this);
- mMapView.setBuiltInZoomControls(true); //启用内置的缩放控件
- bMapController =
mMapView.getController(); - GeoPoint defaultPoint = new
GeoPoint((int) (39.920934 * 1E6),(int) (116.412817 * 1E6));
//用给定的经纬度构造一个GeoPoint,单位是微度 (度 * 1E6) - bMapController.setCenter(defaultPoint); //设置地图中心点
- bMapController.setZoom(12);
//设置地图zoom级别 - mkLocationManager =
mBMapMan.getLocationManager(); - }
- /**
- * 初始化地图管理器BMapManager
- */
- public void init(){
- MapApplication app =
(MapApplication)getApplication(); - if (app.mapManager == null)
{ - app.mapManager = new
BMapManager(getApplication()); - app.mapManager.init(app.mStrKey,
new MapApplication.MyGeneralListener()); - }
- mBMapMan = app.mapManager;
- }
- @Override
- protected void onDestroy() {
- MapApplication app =
(MapApplication)getApplication(); - if (mBMapMan != null) {
- mBMapMan.destroy();
- app.mapManager.destroy();
- app.mapManager = null;
- mBMapMan = null;
- }
- super.onDestroy();
- }
- @Override
- protected void onPause() {
- if (mBMapMan != null)
{ - //
终止百度地图API - mBMapMan.stop();
- }
- super.onPause();
- }
- @Override
- protected void onResume() {
- if (mBMapMan != null)
{ - //
开启百度地图API - mBMapMan.start();
- }
- super.onResume();
- }
- @Override
- protected boolean isRouteDisplayed() {
- return false;
- }
- @Override
- public void onGetAddrResult(MKAddrInfo result, int iError) {
- if(result==null) return;
- SpannableStringBuilder style = new
SpannableStringBuilder(String.format(getResources().getString(R.string.location_text),result.strAddr)); - style.setSpan(new ForegroundColorSpan(Color.RED), 5,
style.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - address_view.setText(style);
- if(dialog!=null) dialog.dismiss();
- }
- @Override
- public void onGetDrivingRouteResult(MKDrivingRouteResult arg0, int arg1)
{} - @Override
- public void onGetPoiResult(MKPoiResult arg0, int arg1, int arg2)
{} - @Override
- public void onGetTransitRouteResult(MKTransitRouteResult arg0, int arg1)
{} - @Override
- public void onGetWalkingRouteResult(MKWalkingRouteResult arg0, int arg1)
{} - /**
- * 重新定位,加载数据
- * @author Administrator
- *
- */
- class MyThread implements Runnable{
- @Override
- public void run() {
- /**
- * 最重要的就是这个玩意
- *
由于LocationListener获取第一个位置修正的时间会很长,为了避免用户等待, - *
在LocationListener获取第一个更精确的位置之前,应当使用getLocationInfo() 获取一个缓存的位置 - */
- Location location =
mkLocationManager.getLocationInfo(); - double lat = 0d,lon =
0d; - if(location!=null){
//定位到位置 - String
coordinate = location.getLatitude()+","+location.getLongitude(); - HotelRemoteData hotelData = new HotelRemoteData();
- /**
- *
远程获取酒店列表数据 - */
- hotelList = hotelData.getHotelToMap(coordinate,distance);
- lat =
location.getLatitude(); - lon =
location.getLongitude(); - }
- Message msg = new
Message(); - Bundle data = new
Bundle(); - data.putDouble("lat",
lat); - data.putDouble("lon",
lon); - msg.setData(data);
- handler.sendMessage(msg);
- }
- }
6、还有一种就是百度示例相当推荐的,也是加载定位位置速度比较快的,那就是通过定位监听器来定位信息。没啥难的,照着百度的示例写,都能搞定。
Java代码
- LocationListener listener = new LocationListener() {
- @Override
- /** 位置变化,百度地图即会调用该方法去获取位置信息。
- *
(我测试发现就算手机不动,它也会偶尔重新去加载位置;只要你通过重力感应,他就一定会重新加载) - */
- public void onLocationChanged(Location location)
{ - GeoPoint gp = new GeoPoint((int)
(location.getLatitude() * 1E6), (int) (location.getLongitude() *
1E6)); //通过地图上的经纬度转换为地图上的坐标点 - bMapController.animateTo(gp);
//动画般的移动到定位的位置 - }
- };