一、吐槽
在百度地图看了几个小时的教程,发现种种问题,很大部分是百度对于定位API 网页上的DEMO代码一大堆错误!这极可能是定位SDK升级后而网页上的DEMO部分代码沿用旧版导致的。
错误1:
在该示例中取了个变量叫mLocationClient,后面居然叫mLocClient,我找了半天,说这变量哪来的呢
错误2:
这个错误是最致命的,在网页上的DEMO(开发指南)里居然连开始定位这个函数至始至终都没调用过!!!
新手咋看以为调用这个就可以定位了,擦,其实还应该调用mLocClient.start(); 才行,否则压根就没启动定位。。。
二、使用百度地图V2.2和定位V4.0实现地图和定位功能
1、首先将必要的库文件导入到你的项目里,具体参看这里
http://developer.baidu.com/map/sdkandev-2.htm
http://developer.baidu.com/map/geosdk-android-developv4.0.htm
2、编写代码 (MainActivity.java)
package com.android.test; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.map.LocationData; import com.baidu.mapapi.map.MapController; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationOverlay; import com.baidu.platform.comapi.basestruct.GeoPoint; public class MainActivity extends Activity { //百度Key private static final String BD_KEY="请在这里输入你的百度地图Key,这里我删除了我自己的,你自己填"; //地图管理器 private BMapManager mBMapMan=null; //地图视图 private MapView mMapView=null; private LocationClient mLocationClient=null; //我的位置覆盖物 private MyLocationOverlay myOverlay; //位置在图层中的索引 private int myOverlayIndex=0; //是否定位到我的位置 private boolean bmyLocal=true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBMapMan=new BMapManager(getApplication()); mBMapMan.init(BD_KEY, null); setContentView(R.layout.activity_main); //注意:请在试用setContentView前初始化BMapManager对象,否则会报错 setContentView(R.layout.activity_main); mMapView=(MapView)findViewById(R.id.bmapsView); mMapView.setBuiltInZoomControls(true); //设置启用内置的缩放控件 MapController mMapController=mMapView.getController(); // 得到mMapView的控制权,可以用它控制和驱动平移和缩放 GeoPoint point =new GeoPoint((int)(39.915* 1E6),(int)(116.404* 1E6)); //用给定的经纬度构造一个GeoPoint,单位是微度 (度 * 1E6) mMapController.setCenter(point);//设置地图中心点 mMapController.setZoom(12);//设置地图zoom级别 ////////////////////////定位功能代码开始 mLocationClient=new LocationClient(this); mLocationClient.setAK(BD_KEY); myOverlay=new MyLocationOverlay(mMapView); LocationClientOption option=new LocationClientOption(); option.setOpenGps(true); option.setAddrType("all");//返回的定位结果包含地址信息 option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02 //当不设此项,或者所设的整数值小于1000(ms)时,采用一次定位模式。 //option.setScanSpan(5000);//设置发起定位请求的间隔时间为5000ms option.disableCache(true);//禁止启用缓存定位 option.setPoiNumber(5); //最多返回POI个数 option.setPoiDistance(1000); //poi查询距离 option.setPoiExtraInfo(true); //是否需要POI的电话和地址等详细信息 mLocationClient.setLocOption(option); //注册位置监听 mLocationClient.registerLocationListener(locationListener); if(mLocationClient!=null&&!mLocationClient.isStarted()) { mLocationClient.requestLocation(); mLocationClient.start(); } else Log.e("LocSDK3", "locClient is null or not started"); } private BDLocationListener locationListener=new BDLocationListener() { @Override public void onReceiveLocation(BDLocation arg0) { Dispose(arg0); } @Override public void onReceivePoi(BDLocation arg0) { Dispose(arg0); } private void Dispose(BDLocation location) { if(location==null) return; StringBuffer sb = new StringBuffer(256); sb.append("time : "); sb.append(location.getTime()); sb.append(" error code : "); sb.append(location.getLocType()); sb.append(" latitude : "); sb.append(location.getLatitude()); sb.append(" lontitude : "); sb.append(location.getLongitude()); sb.append(" radius : "); sb.append(location.getRadius()); if (location.getLocType() == BDLocation.TypeGpsLocation){ sb.append(" speed : "); sb.append(location.getSpeed()); sb.append(" satellite : "); sb.append(location.getSatelliteNumber()); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){ sb.append(" addr : "); sb.append(location.getAddrStr()); } //poiLocation if(location.hasPoi()){ sb.append(" Poi:"); sb.append(location.getPoi()); }else{ sb.append(" noPoi information"); } //需要定位到我的位置? if(bmyLocal) { double lat=location.getLatitude(); double lon=location.getLongitude(); LocationData data=new LocationData(); data.latitude=lat; data.longitude=lon; data.direction=2.0f; myOverlay.setData(data); //检查覆盖物是否存在,存在则修改,否则则添加 if(mMapView.getOverlays().contains(myOverlay)) { mMapView.getOverlays().set(myOverlayIndex,myOverlay); } else{ myOverlayIndex=mMapView.getOverlays().size(); mMapView.getOverlays().add(myOverlay); } GeoPoint geoPoint=new GeoPoint((int)(lat* 1E6),(int)(lon* 1E6)); mMapView.getController().setCenter(geoPoint); mMapView.refresh(); bmyLocal=false; } Log.e("定位结果:",sb.toString()); } }; //创建菜单 @Override public boolean onCreateOptionsMenu(Menu menu) { //组、ID、排序、菜单名 menu.add(0,1,1,"我的位置").setIcon(R.drawable.root_icon); return true; } //处理菜单 @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case 1: //我的位置 bmyLocal=true; mLocationClient.requestLocation(); mLocationClient.start(); break; } return true; } @Override protected void onDestroy(){ if(mLocationClient!=null&&mLocationClient.isStarted()) mLocationClient.stop(); mMapView.destroy(); if(mBMapMan!=null){ mBMapMan.destroy(); mBMapMan=null; } super.onDestroy(); } @Override protected void onPause(){ mMapView.onPause(); if(mBMapMan!=null){ mBMapMan.stop(); } super.onPause(); } @Override protected void onResume(){ mMapView.onResume(); if(mBMapMan!=null){ mBMapMan.start(); } super.onResume(); } }
3、在AndroidManifest.xml里注册和添加权限
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.test" android:versionCode="1" android:versionName="1.0" > <!-- 添加屏幕及版本支持 --> <supports-screens android:largeScreens="true" android:normalScreens="true" android:smallScreens="true" android:resizeable="true" android:anyDensity="true"/> <uses-sdk android:minSdkVersion="7" /> <!-- 在sdcard中创建/删除文件的权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 挂载和反挂载的权限 --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 读取手机状态 ,如来了新电话--> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 震动权限 --> <uses-permission android:name="android.permission.VIBRATE" /> <!-- 网络访问权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- 百度地图定位功能所需权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <permission android:name="android.permission.BAIDU_LOCATION_SERVICE" /> <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_GPS"/> <uses-permission android:name="android.permission.READ_LOGS" /> <application android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.Black" android:persistent="true" > <activity android:name=".MainActivity" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 百度定位服务 android:permission="android.permission.BAIDU_LOCATION_SERVICE">--> <service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"> </service> </application> </manifest>
上述代码个人做了些删除和修改,代码只包含主要的,如果有问题,请酌情修改配置即可。
然后程序效果如图:
百度定位号称使用GPS、网络定位(WIFI、基站)混合定位模式,现在我使用的是移动的2G手机网络,定位结果偏差还是很大的,因为它使用的基站定位,意思就是需找到了我手机发送信号的基站(信号塔)的位置,偏差至少500米,实际上我应该在紫薇北路附近。
但是当打开WIFI去定位,发现很准确,误差在50米以内!所以如果你在外面逛的话,建议打开WIFI联网,进行定位,效果更可靠。
如果你使用GPS定位的话,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵,呵呵。。。。