新手上路,这几天在弄百度地图SDK的使用(吐槽 : 官网上的开发指南简直就是实力坑爹,可能是开发人员太忙,维护不及时吧),我对本次学习的要求也不高:能正常显示地图,能定位,能添加mark(覆盖物),点击mark时能提示当前位置信息就行,再深的东西,以后有时间再去研究吧,毕竟新手还是欠火候。
因为软件开发更新换代太快,各位看官看的时候可能本文内容就已经过时了,所以先交代一下开发环境:
应用开发开发工具:
Android Studio 1.5.1
百度地图版本信息:
Android 地图 SDK v3.7.1
Android 定位 SDK v6.2.2
废话多说,先来一发截图,一眼就能看出来到底实现了哪些功能:
图1-1.实现定位
图1-2.拖拽到新的位置
如上面两幅图所示,图1-1显示的是当程序正常运行后,就会定位到当前位置,显示位置信息(’气泡’),图1-2显示的是当拖动mark到新的位置后,显示当前的位置信息,大家可能注意到图1-2右下角红色圆圈圈住的图标,是可以点击的,作用是实现重新定位。
去百度开发者中心下载最新的开发包,现在是支持按功能需求来下载开发包,我就贪婪的全都下载了(下载地址),最好的学习方式就是下载示例代码,模仿着写。解压下载好的库文件。
首先:在工程app/libs目录下放入BaiduLBS_Android.jar包,如图2-1所示。
然后:在src/main/目录下新建jniLibs目录,在jniLibs新建armeabi文件(这个文件要根据你的手机的cpu类型来创建,armeabi就是针对普通的或旧的arm cpu,armeabi-v7a是针对有浮点运算或高级扩展功能的arm cpu),然后把动态链接库.so文件拷贝到该目录下,如图2-2所示。
最后:对于每个jar文件,右键-选择Add As Library,导入到工程中。
图2-1.导入jar包文件
图2-2.导入.so库文件
环境配置也可以参考官方指南.
修改activity_main.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.yu.baidumapdemo.MainActivity">
<TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="百 度 地 图" />
<com.baidu.mapapi.map.MapView android:id="@+id/map_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/title" android:clickable="true"/>
<Button android:id="@+id/request_location" android:layout_width="45dp" android:layout_height="45dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="5dp" android:layout_marginLeft="50dp" android:background="@drawable/custom_loc"/>
</RelativeLayout>
布局文件如上所述,很简单,一个TextView显示一个标题(之后我用它来显示当前位置),一个com.baidu.mapapi.map.MapView,这是最重要的用来,是显示地图的控件,最后放了一个Button,就是图1-2中红圈所示的按钮,用来重新获取定位。
新建类 BaiduMapDemoApplication继承自Application
package com.yu.baidumapdemo;
import android.app.Application;
import com.baidu.mapapi.SDKInitializer;
/** * Created by yu on 2016-03-09. */
public class BaiduMapDemoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext
//这样就不用每个Activity都初始化一遍了
SDKInitializer.initialize(this);
}
}
这个类的功能很简单,因为在使用百度地图的所有功能前都需要调用SDKInitializer.initialize(android.content.Context);来初始化组件,所以新建这个类继承自Application,并在AndroidManifest.xml文件进行配置(为application添加属性 android:name=“.BaiduMapDemoApplication”),保证最先得到初始化。
MainActivity.java:
package com.yu.baidumapdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import java.util.List;
//Ak(百度密钥): 8w4BMfqde5lkbGy3xz6h6Y7C
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity"; //日志的TAG
private Button requestButton = null; //重新定位按钮
private TextView locationText = null; //显示位置信息的TextView
private MapView mapView = null; //显示地图的控件
private BaiduMap baiduMap = null; //地图管理器
private Marker marker = null ; //覆盖物
//初始化bitmap信息,不用的时候请及时回收recycle //覆盖物图标
private BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.location_arrows);
//定位服务的客户端。宿主程序在客户端声明此类,并调用,目前只支持在主线程中启动
private LocationClient locationClient = null;
//是否是首次定位,实际上没有用到,因为我设置了不定时请求位置信息
boolean isFirstLoc = true;
//定位监听器(实现定位请求回调接口),当客户端请求定位或者开始定位的时候会触发
public BDLocationListener myListener = new BDLocationListener() {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
Log.d(TAG, "BDLocationListener -> onReceiveLocation");
String addr; //定位结果
//mapView销毁后不在处理新接收的位置
if(bdLocation == null || mapView == null) {
Log.d(TAG, "BDLocation or mapView is null");
locationText.setText("定位失败...");
return;
}
if(!bdLocation.getLocationDescribe().isEmpty()) {
addr = bdLocation.getLocationDescribe();
}else if (bdLocation.hasAddr()) {
addr = bdLocation.getAddrStr();
}else {
Log.d(TAG, "BDLocation has no addr info");
addr = "定位失败...";
return;
}
//以下打印日志,打印一些详细信息,供参考
//------------------------------------位置信息日志--------------------------------------------------
StringBuilder sBuilder = new StringBuilder();
sBuilder.append("\nTime : " + bdLocation.getTime()); //服务器返回的当前定位时间
sBuilder.append("\nError code : " + bdLocation.getLocType()); //定位结果码
sBuilder.append("\nLatitude : " + bdLocation.getLatitude()); //获取纬度坐标
sBuilder.append("\nLongtitude : " + bdLocation.getLongitude()); //获取经度坐标
sBuilder.append("\nRadius : " + bdLocation.getRadius()); //位置圆心
//根据定位结果码判断是何种定位以及定位请求是否成功
if(bdLocation.getLocType() == BDLocation.TypeGpsLocation) {
//GPS定位结果
sBuilder.append("\nSpeed : " + bdLocation.getSpeed());//当前运动的速度
sBuilder.append("\nSatellite number : " + bdLocation.getSatelliteNumber());//定位卫星数量
sBuilder.append("\nHeight : " + bdLocation.getAltitude()); //位置高度
sBuilder.append("\nDirection : " + bdLocation.getDirection()); //定位方向
sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr()); //位置详细信息
sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
sBuilder.append("\nDescribtion : GPS 定位成功");
}else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation) {
//网络定位结果
sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr()); //位置详细信息
sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
sBuilder.append("\nOperators : " + bdLocation.getOperators());//运营商编号
sBuilder.append("\nDescribtion : 网络定位成功");
}else if(bdLocation.getLocType() == BDLocation.TypeOffLineLocation) {
//离线定位结果
sBuilder.append("\nAddrStr : " + bdLocation.getAddrStr()); //位置详细信息
sBuilder.append("\nStreet : " + bdLocation.getStreetNumber() + " " + bdLocation.getStreet());//街道号、路名
sBuilder.append("\nDescribtion : 离线定位成功");
}else if(bdLocation.getLocType() == BDLocation.TypeServerError) {
sBuilder.append("\nDescribtion : 服务端网络定位失败,可以反馈IMEI号和大体定位时间到[email protected],会有人追查原因");
}else if(bdLocation.getLocType() == BDLocation.TypeNetWorkException) {
sBuilder.append("\nDescribtion : 网络故障,请检查网络连接是否正常");
}else if(bdLocation.getLocType() == BDLocation.TypeCriteriaException) {
sBuilder.append("\nDescribtion : 无法定位结果,一般由于定位SDK内部检测到没有有效的定位依据," +
"比如在飞行模式下就会返回该定位类型, 一般关闭飞行模式或者打开wifi就可以再次定位成功");
}
//位置语义化描述
sBuilder.append("\nLocation decribe : " + bdLocation.getLocationDescribe());
//poi信息(就是附近的一些建筑信息),只有设置可获取poi才有值
List<Poi> poiList = bdLocation.getPoiList();
if(poiList != null) {
sBuilder.append("\nPoilist size : " + poiList.size());
for (Poi p : poiList) {
sBuilder.append("\nPoi : " + p.getId() + " " + p.getName() + " " + p.getRank());
}
}
//打印以上信息
Log.d(TAG, "定位结果详细信息 : " + sBuilder.toString());
//----------------------------------------------定位----------------------------------------
//构建生成定位数据对象 //定位数据构建器
MyLocationData myLocationData = new MyLocationData.Builder()
.accuracy(bdLocation.getRadius()) //设置定位数据的精度信息,单位米
.direction(100) //设定定位数据的方向信息??啥意思??
.latitude(bdLocation.getLatitude()) //设定定位数据的纬度
.longitude(bdLocation.getLongitude())//设定定位数据的经度
.build(); //构建生生定位数据对象
//设置定位数据, 只有先允许定位图层后设置数据才会生效,setMyLocationEnabled(boolean)
baiduMap.setMyLocationData(myLocationData);
if(isFirstLoc) {
//Log.d(TAG,"首次定位开始");
//isFirstLoc = false;
//地理坐标基本数据结构:经度和纬度
LatLng latLng = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
//为当前定位到的位置设置覆盖物Marker
resetOverlay(latLng);
//描述地图状态将要发生的变化 //生成地图状态将要发生的变化,newLatLngZoom设置地图新中心点
MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng,18.0f);
//MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng);
//以动画方式更新地图状态,动画耗时 300 ms (聚焦到当前位置)
baiduMap.animateMapStatus(mapStatusUpdate);
}
locationText.setText(addr);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现//最好使用全局的Context 即用getApplicationContext()
//SDKInitializer.initialize(getApplicationContext());//由于已在BaiduMapDemoApplication中初始化过,就不再次初始化
setContentView(R.layout.activity_main);//加载布局文件
//获取地图控件的引用
mapView = (MapView) findViewById(R.id.map_view);
//重新定位按钮
requestButton = (Button) findViewById(R.id.request_location);
//定位结果显示
locationText = (TextView) findViewById(R.id.title);
locationText.setText("正在定位...");
//获取地图控制器
baiduMap = mapView.getMap();
//允许定位图层,如果不设置这个参数,那么baiduMap.setMyLocationData(myLocationData);定位不起作用
baiduMap.setMyLocationEnabled(true);
//设置mark覆盖物拖拽监听器
baiduMap.setOnMarkerDragListener(new MyMarkerDragListener());
//设置mark覆盖物点击监听器
baiduMap.setOnMarkerClickListener(new MyMarkerClickListener());
//生成定位服务的客户端对象,此处需要注意:LocationClient类必须在主线程中声明
locationClient = new LocationClient(getApplicationContext());
//注册定位监听函数,当开始定位.start()或者请求定位.requestLocation()时会触发
locationClient.registerLocationListener(myListener);
//设定定位SDK的定位方式
setLocationOption();
//开始、请求定位
//locationClient.start();
requestLocation();
//重新定位按钮设置监听器
requestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//开始定位,或者重新定位
requestLocation();
}
});
}
//开始定位或者请求定位
private void requestLocation() {
//如果请求定位客户端已经开启,就直接请求定位,否则开始定位
//很重要的一点,是要在AndroidManifest文件中注册定位服务,否则locationClient.isStarted一直会是false,
// 而且可能出现一种情况是首次能定位,之后再定位无效
if(locationClient != null && locationClient.isStarted()) {
Log.d(TAG, "requestLocation.");
locationText.setText("正在定位...");
//请求定位,异步返回,结果在locationListener中获取.
locationClient.requestLocation();
}else if (locationClient != null && !locationClient.isStarted()) {
Log.d(TAG, "locationClient is started : " + locationClient.isStarted());
locationText.setText("正在定位...");
//定位没有开启 则开启定位,结果在locationListener中获取.
locationClient.start();
}else {
Log.e(TAG,"request location error!!!");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
//注销定位监听器
locationClient.unRegisterLocationListener(myListener);
//停止定位
locationClient.stop();
//不允许图层定位
baiduMap.setMyLocationEnabled(false);
//清除覆盖物
clearOverlay();
//回收Bitmap资源
bd.recycle();
//在activity执行onDestroy时执行MapView.onDestroy(),实现地图生命周期管理
mapView.onDestroy();
mapView = null;
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
//在activity执行onResume时执行MapView. onResume(),实现地图生命周期管理
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
//在activity执行onPause时执行MapView. onResume(),实现地图生命周期管理
mapView.onPause();
}
//设定定位服务客户端locationClient的定位方式
private void setLocationOption(){
//获取配置参数对象,用于配置定位SDK各配置参数,比如定位模式、定位时间间隔、坐标系类型等
LocationClientOption option = new LocationClientOption();
//可选,默认false,设置是否使用gps
option.setOpenGps(true);
/* * 高精度定位模式:这种定位模式下,会同时使用网络定位和GPS定位,优先返回最高精度的定位结果; * 低功耗定位模式:这种定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位); * 仅用设备定位模式:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位。*/
//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,默认gcj02,设置返回的定位结果坐标系
option.setCoorType("bd09ll");
//可选,默认0,即仅定位一次,设置定时发起定位请求的间隔需要大于等于1000ms才是有效的
/* * 定位sdk提供2种定位模式,定时定位和app主动请求定位。 * setScanSpan < 1000 则为 app主动请求定位; * setScanSpan >=1000,则为定时定位模式(setScanSpan的值就是定时定位的时间间隔)) * 定时定位模式中,定位sdk会按照app设定的时间定位进行位置更新,定时回调定位结果。此种定位模式适用于希望获得连续定位结果的情况。 * 对于单次定位类应用,或者偶尔需要一下位置信息的app,可采用app主动请求定位这种模式。*/
//option.setScanSpan(2000);
//可选,设置是否需要地址信息,默认不需要
option.setIsNeedAddress(true);
//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
option.setIsNeedLocationDescribe(true);
//设置是否需要返回位置POI信息,可以在BDLocation.getPoiList()中得到数据
option.setIsNeedLocationPoiList(true);
//在网络定位时,是否需要设备方向 true:需要 ; false:不需要
option.setNeedDeviceDirect(true);
//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
option.setIgnoreKillProcess(false);
//可选,默认false,设置是否收集CRASH信息,默认收集
option.SetIgnoreCacheException(false);
//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
option.setEnableSimulateGps(false);
//设定定位SDK的定位方式
locationClient.setLocOption(option);
}
//初始化添加覆盖物mark
private void initOverlay(LatLng latLng) {
Log.d(TAG, "Start initOverlay");
//设置覆盖物添加的方式与效果
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)//mark出现的位置
.icon(bd) //mark图标
.draggable(true)//mark可拖拽
.animateType(MarkerOptions.MarkerAnimateType.drop)//从天而降的方式
//.animateType(MarkerOptions.MarkerAnimateType.grow)//从地生长的方式
;
//添加mark
marker = (Marker) (baiduMap.addOverlay(markerOptions));//地图上添加mark
//弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
setPopupTipsInfo(marker);
Log.d(TAG,"End initOverlay");
}
//清除覆盖物
private void clearOverlay(){
baiduMap.clear();
marker = null;
}
//重置覆盖物
private void resetOverlay(LatLng latLng) {
clearOverlay();
initOverlay(latLng);
}
//覆盖物拖拽监听器
public class MyMarkerDragListener implements BaiduMap.OnMarkerDragListener {
@Override
public void onMarkerDrag(Marker marker) {
}
//拖拽结束,调用方法,弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
@Override
public void onMarkerDragEnd(Marker marker) {
setPopupTipsInfo(marker);
}
@Override
public void onMarkerDragStart(Marker marker) {
}
}
//覆盖物点击监听器
public class MyMarkerClickListener implements BaiduMap.OnMarkerClickListener {
@Override
public boolean onMarkerClick(Marker marker) {
//调用方法,弹出View(气泡,意即在地图中显示一个信息窗口),显示当前mark位置信息
setPopupTipsInfo(marker);
return false;
}
}
//想根据Mark中的经纬度信息,获取当前的位置语义化结果,需要使用地理编码查询和地理反编码请求
//在地图中显示一个信息窗口
private void setPopupTipsInfo(Marker marker){
//获取当前经纬度信息
final LatLng latLng = marker.getPosition();
final String[] addr = new String[1];
//实例化一个地理编码查询对象
GeoCoder geoCoder = GeoCoder.newInstance();
//设置反地理编码位置坐标
ReverseGeoCodeOption option = new ReverseGeoCodeOption();
option.location(latLng);
//发起反地理编码请求
geoCoder.reverseGeoCode(option);
//为地理编码查询对象设置一个请求结果监听器
geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
Log.d(TAG, "地理编码信息 ---> \nAddress : " + geoCodeResult.getAddress()
+ "\ntoString : " + geoCodeResult.toString()
+ "\ndescribeContents : " + geoCodeResult.describeContents());
}
//当获取到反编码信息结果的时候会调用
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
//获取地理反编码位置信息
addr[0] = reverseGeoCodeResult.getAddress();
//获取地址的详细内容对象,此类表示地址解析结果的层次化地址信息。
ReverseGeoCodeResult.AddressComponent addressDetail = reverseGeoCodeResult.getAddressDetail();
Log.d(TAG, "反地理编码信息 ---> \nAddress : " + addr[0]
+ "\nBusinessCircle : " + reverseGeoCodeResult.getBusinessCircle()//位置所属商圈名称
+ "\ncity : " + addressDetail.city //所在城市名称
+ "\ndistrict : " + addressDetail.district //区县名称
+ "\nprovince : " + addressDetail.province //省份名称
+ "\nstreet : " + addressDetail.street //街道名
+ "\nstreetNumber : " + addressDetail.streetNumber);//街道(门牌)号码
StringBuilder poiInfoBuilder = new StringBuilder();
//poiInfo信息
List<PoiInfo> poiInfoList = reverseGeoCodeResult.getPoiList();
if(poiInfoList != null) {
poiInfoBuilder.append("\nPoilist size : " + poiInfoList.size());
for (PoiInfo p : poiInfoList) {
poiInfoBuilder.append("\n\taddress: " + p.address);//地址信息
poiInfoBuilder.append(" name: " + p.name + " postCode: " + p.postCode);//名称、邮编
//还有其他的一些信息,我这里就不打印了,请参考API
}
}
Log.d(TAG,"poiInfo --> " + poiInfoBuilder.toString());
//动态创建一个View用于显示位置信息
Button button = new Button(getApplicationContext());
//设置view是背景图片
button.setBackgroundResource(R.drawable.location_tips);
//设置view的内容(位置信息)
button.setText(addr[0]);
//在地图中显示一个信息窗口,可以设置一个View作为该窗口的内容,也可以设置一个 BitmapDescriptor 作为该窗口的内容
InfoWindow infoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(button), latLng, -47, new InfoWindow.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick() {
//当InfoWindow被点击后隐藏
baiduMap.hideInfoWindow();
}
});
//InfoWindow infoWindow = new InfoWindow(button, latLng, -47);
//显示信息窗口
baiduMap.showInfoWindow(infoWindow);
}
});
/*不能放在下面 因为可能得到的数据还没来得及回调 Button button = new Button(getApplicationContext()); button.setBackgroundResource(R.drawable.location_tips); button.setText(addr[0]); //InfoWindow infoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(button),latLng,-47,null); InfoWindow infoWindow = new InfoWindow(button,latLng,-47); baiduMap.showInfoWindow(infoWindow); */
return ;
}
}
应为上面的代码注释很详细,这里简单介绍一下流程:
首先:获取地图显示控件对象MapView -> mapView
然后:获取地图控制对象BaiduMap -> baiduMap,并允许显示图层定位
再后:为baiduMap设置监听器:覆盖物拖拽监听器,覆盖物点击监听器(二者的主要作用是在地图中显示一个信息窗口,来提示用户当前的位置信息)
接着:获取定位服务客户端对象 LocationClient -> locationClient,并注册定位监听函数(BDLocationListener)以及设置定位方式
最后:调用locationClient .start()开启定位或者如果定位服务已开启,则调用locationClient .requestLocation()再次请求定位,这两个方法成功调用后,会触发定位监听器(BDLocationListener),然后监听器中获取定位结果以及定位信息,并且添加覆盖物和显示信息窗口(气泡)。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yu.baidumapdemo">
<!--读取系统设置的数据库(launcher.db)的权限-->
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<!--屏幕保持唤醒 不锁屏-->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!--允许应用程序更改主屏幕中的设置和快捷方式-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用于读取手机当前的状态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡读取权限,用户写入离线定位数据-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<application android:name=".BaiduMapDemoApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
<meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="8w4BMfqde5lkbGy3xz6h6Y7C"/>
</application>
</manifest>
增加以下四个配置(很重要):
1). 增加权限的申请
2). 注册application初始化SDK,即:
为application添加属性 android:name=“.BaiduMapDemoApplication”
3). 注册定位服务(com.baidu.location.f),这个服务如果不注册,会导致无法进行定位
4). 配置密钥(AK)