公司原来项目里有使用百度地图,是比较老的v2_1_0版本,在android5.0一下版本测试没什么问题,在5.0以上就会报错明明有mapview,但是却找不到,导致程序异常退出(android.view.InflateException: Binary XML file line #50: Error inflating class com.baidu.mapapi.map.MapView),网上找了好久发现好多人遇到一样的错误,但是确实不一样的问题,大多数人遇到的没有调用SDKInitializer.initialize(getApplicationContext());初始化。去百度地图论坛上发帖子,有人回我要我去更新到最新的版本,我原先也想过要更新到最新的百度地图的sdk,发现百度地图的改动挺大,就像图层ItemizedOverlay,最新的版本好像这个类被去掉了,好多的方法也有改动,于是想偷懒能不能再原来版本的基础上改一下就算了,毕竟改别人写的项目是很烦人的(特别是没有注释的情况下);最终还是选择就更新到最新的sdk,顺便学习一下百度地图开发。记录一下自己学习过程遇到的问题,和解决办法。
首先是创建应用和获取密匙,这里用到的签名方式是SHA1并不是申请qq和微信分享用到的md5签名
然后后将获得密匙配置到androidmanifest.xml文件中
还需要添加一个服务
发现去掉这个服务也能定位我当前的位置,难道我弄错了什么?
下面上正式代码
MapView mMapView;
/***
* 是否是第一次定位
*/
private volatile boolean isFristLocation = true;
private List<Map<String, String>> datalist;
/**
* 最新一次的经纬度
*/
private double mCurrentLantitude;
private double mCurrentLongitude;
/**
* 当前的精度
*/
private float mCurrentAccracy;
/**
* 定位的客户端
*/
private LocationClient mLocationClient;
/**
* 地图实例
*/
private BaiduMap mBaiduMap;
/**
* 当前定位的模式
*/
private LocationMode mCurrentMode = LocationMode.NORMAL;
/**
* 方向传感器的监听器
*/
private MyOrientationListener myOrientationListener;
/**
* 定位的监听器
*/
public MyLocationListener mMyLocationListener;
/**
* 方向传感器X方向的值
*/
private int mXDirection;
private BitmapDescriptor mIconMaker;
private View infoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
//初始化
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.environment_map_activity);
mMapView = (MapView) this.findViewById(R.id.environment_map_View);
mIconMaker = BitmapDescriptorFactory.fromResource(R.drawable.tip_red);
// 第一次定位
isFristLocation = true;
// 获取地图控件引用
// 获得地图的实例
mBaiduMap = mMapView.getMap();
//设置地图的缩放比
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(12.0f);
mBaiduMap.setMapStatus(msu);
// 初始化定位
initMyLocation();
// 初始化传感器
initOritationListener();
//设置地图点击事件
initMapClickEvent();
//添加图层标志点击事件 需要该类实现监听OnMarkerClickListener
mBaiduMap.setOnMarkerClickListener(this);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Get_Gps();
}
}).start();
}
private void initMapClickEvent()
{
mBaiduMap.setOnMapClickListener(new OnMapClickListener()
{
@Override
public boolean onMapPoiClick(MapPoi arg0)
{
return false;
}
@Override
public void onMapClick(LatLng arg0)
{
mBaiduMap.hideInfoWindow();
}
});
}
private void initMyLocation() {
// 定位初始化
mLocationClient = new LocationClient(this);
mMyLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(mMyLocationListener);
// 设置定位的相关配置
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);// 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
mLocationClient.setLocOption(option);
}
<span style="white-space:pre"> </span>/**
* 定位回调监听
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
// map view 销毁后不在处理新接收的位置
if (location == null || mMapView == null)
return;
// 构造定位数据
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(mXDirection).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
mCurrentAccracy = location.getRadius();
// 设置定位数据
mBaiduMap.setMyLocationData(locData);
mCurrentLantitude = location.getLatitude();
mCurrentLongitude = location.getLongitude();
// 设置自定义图标
BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
.fromResource(R.drawable.location_me);
MyLocationConfiguration config = new MyLocationConfiguration(
mCurrentMode, true, mCurrentMarker);
// mBaiduMap.setMyLocationConfigeration(config);
// 第一次定位时,将地图位置移动到当前位置
if (isFristLocation) {
isFristLocation = false;
LatLng ll = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
mBaiduMap.animateMapStatus(u);
}
}
}
/**
* 初始化方向传感器
*/
private void initOritationListener() {
myOrientationListener = new MyOrientationListener(
getApplicationContext());
myOrientationListener
.setOnOrientationListener(new OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mXDirection = (int) x;
// 构造定位数据
MyLocationData locData = new MyLocationData.Builder()
.accuracy(mCurrentAccracy)
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(mXDirection)
.latitude(mCurrentLantitude)
.longitude(mCurrentLongitude).build();
// 设置定位数据
mBaiduMap.setMyLocationData(locData);
// 设置自定义图标
BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
.fromResource(R.drawable.location_me);
MyLocationConfiguration config = new MyLocationConfiguration(
mCurrentMode, true, mCurrentMarker);
// mBaiduMap.setMyLocationConfigeration(config);
}
});
}
/**
* 初始化图层
*/
public void addInfosOverlay(List<Environment> infos) {
// synchronized (mIconMaker) {
mBaiduMap.clear();
LatLng latLng = null;
OverlayOptions overlayOptions = null;
Marker marker = null;
for (Environment info : infos) {
// 位置
latLng = new LatLng(info.getmLat(), info.getMlon());
// 图标
overlayOptions = new MarkerOptions().position(latLng)
.icon(mIconMaker).zIndex(5);
marker = (Marker) (mBaiduMap.addOverlay(overlayOptions));
Bundle bundle = new Bundle();
bundle.putSerializable("environment",environment);
marker.setExtraInfo(bundle);
}
// }
}
/**
* 图层标志的点击事件
*/
@Override
public boolean onMarkerClick(Marker marker) {
// TODO Auto-generated method stub
Environment info = (Environment) marker.getExtraInfo().get("info");
InfoWindow mInfoWindow;
// 将marker所在的经纬度的信息转化成屏幕上的坐标
final LatLng ll = marker.getPosition();
Point p = mBaiduMap.getProjection().toScreenLocation(ll);
Log.e("000", "--!" + p.x + " , " + p.y);
// p.y -= 47;
LatLng llInfo = mBaiduMap.getProjection().fromScreenLocation(p);
// 为弹出的InfoWindow添加点击事件
mInfoWindow=new InfoWindow(getInfoWindoView(marker, info.getCode()), llInfo,-47);
// 显示InfoWindow
mBaiduMap.showInfoWindow(mInfoWindow);
return true;
}
我自定义了一个方法 getInfoWindoView返回一个view对象
TextView map_tvname;
TextView map_first;
TextView map_data;
ImageView map_img_great;
ImageView map_img_good;
ImageView map_img_bad;
private View getInfoWindoView(final Marker marker, final String code) {
if (null == infoView) {
infoView = (ViewGroup) LayoutInflater.from(this).inflate(
R.layout.pop_environment_indoor, null);
}
map_tvname = (TextView) infoView.findViewById(R.id.map_tvname);
map_first = (TextView) infoView.findViewById(R.id.map_first);
map_data = (TextView) infoView.findViewById(R.id.map_data);
map_img_great = (ImageView) infoView.findViewById(R.id.map_img_great);
map_img_good = (ImageView) infoView.findViewById(R.id.map_img_good);
map_img_bad = (ImageView) infoView.findViewById(R.id.map_img_bad);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
HttpPost httpPost = new HttpPost("url");
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("code", code));
params.add(new BasicNameValuePair("key", ascllEncrypt.datedata()));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
HttpResponse httpResponse = new DefaultHttpClient()
.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = httpResponse.getEntity();
XMLUtils xmlUtils = new XMLUtils();
datalist = xmlUtils.GetEnvironmentMapData(entity.getContent());
Message message = mHandler.obtainMessage();
message.what = 0x11;
mHandler.sendMessage(message);
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e)
e.printStackTrace();
}
这里代码确实有点乱,我也觉得很不爽,先这样看着吧
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0x11) {
//在这里做infowindow中view的设置
map_tvname.setTextView();
...
}
差点忘了还有一些内容,设置定位间隔时间,一旦启动定位,会不断获取的定位,需要在onstop,onstart,onresume,ondestoy 方法中做一些操作,以及对BitmapDescriptor对象的回收
@Override
protected void onStart() {
// 开启图层定位
mBaiduMap.setMyLocationEnabled(true);
if (!mLocationClient.isStarted()) {
mLocationClient.start();
}
// 开启方向传感器
myOrientationListener.start();
super.onStart();
}
@Override
protected void onStop() {
// 关闭图层定位
mBaiduMap.setMyLocationEnabled(false);
mLocationClient.stop();
// 关闭方向传感器
myOrientationListener.stop();
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mMapView.onDestroy();
mIconMaker.recycle();
mMapView = null;
}
@Override
protected void onResume() {
super.onResume();
// 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
}
还有一个方向传感器的监听类
public class MyOrientationListener implements SensorEventListener
{
private Context context;
private SensorManager sensorManager;
private Sensor sensor;
private float lastX ;
private OnOrientationListener onOrientationListener ;
public MyOrientationListener(Context context)
{
this.context = context;
}
public void start()
{
// 获得传感器管理器
sensorManager = (SensorManager) context
.getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null)
{
// 获得方向传感器
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
// 注册
if (sensor != null)
{//SensorManager.SENSOR_DELAY_UI
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_UI);
}
}
public void stop()
{
sensorManager.unregisterListener(this);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
}
@Override
public void onSensorChanged(SensorEvent event)
{
// 接受方向感应器的类型
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION)
{
// 这里我们可以得到数据,然后根据需要来处理
float x = event.values[SensorManager.DATA_X];
if( Math.abs(x- lastX) > 1.0 )
{
onOrientationListener.onOrientationChanged(x);
}
// Log.e("DATA_X", x+"");
lastX = x ;
}
}
public void setOnOrientationListener(OnOrientationListener onOrientationListener)
{
this.onOrientationListener = onOrientationListener ;
}
public interface OnOrientationListener
{
void onOrientationChanged(float x);
}
}
自定义图标
BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory.fromResource(R.drawable.location_me);
MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
mBaiduMap.setMyLocationConfigeration(config);
然后我就勉强用他的默认的了。如果大家有解决办法可以和我说,谢谢
写的不是很好,最重要的是记录自己学习的东西吧,把它写出来可能记得更好,也方便一些和我遇到一样问题的童鞋,一起交流,这其中很多代码借鉴张鸿洋大哥的博客,