环境配置
将解压后的开发包libs文件夹内的内容全部复制到工程app/libs目录下
在app\build.gradle文件中添加依赖
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
在清单中添加开发秘钥及权限
<!-- 百度地图 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="xxxxxx" /> <!-- key:开发者申请的Key -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
布局文件中添加地图控件
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
创建地图
public class MapActivity extends Activity {
MapView mMapView = null;
BaiduMap mBaiduMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 在使用SDK各组件之前初始化context信息,传入ApplicationContext
// 注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.map);
// 获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
initView();
}
private void initView() {
mBaiduMap = mMapView.getMap();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mMapView.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
// 在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
// 在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
}
此时,运行程序可看到如下界面:
实时路况图:setTrafficEnabled()
城市热力图:setBaiduHeatMapEnabled() ,百度地图开放平台有更详细介绍,可定制专属热力图
// 实时交通
ImageButton ibRoad;
private boolean isRoadOpen = false;
// 城市热力图
ImageButton ibHeat;
private boolean isHeatOpen = false;
ibRoad = (ImageButton) findViewById(R.id.btn_road);
ibHeat = (ImageButton) findViewById(R.id.btn_heat);
ibHeat.setOnClickListener(this);
ibRoad.setOnClickListener(this);
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_road:
if (isRoadOpen) {
// 关闭交通图
mBaiduMap.setTrafficEnabled(false);
ibRoad.setImageResource(R.drawable.road_normal);
isRoadOpen = false;
Log.i(TAG, "关闭交通图");
} else {
// 开启交通图
mBaiduMap.setTrafficEnabled(true);
ibRoad.setImageResource(R.drawable.road_light);
isRoadOpen = true;
Log.i(TAG, "开启交通图");
}
break;
case R.id.btn_heat:
if (isHeatOpen) {
// 关闭城市热力图
mBaiduMap.setBaiduHeatMapEnabled(false);
ibHeat.setImageResource(R.drawable.heat_normal);
isHeatOpen = false;
Log.i(TAG, "关闭城市热力图");
} else {
// 开启城市热力图
mBaiduMap.setBaiduHeatMapEnabled(true);
ibHeat.setImageResource(R.drawable.heat_light);
isHeatOpen = true;
Log.i(TAG, "开启城市热力图");
}
break;
}
}
效果:
定位
首先在清单中声明service组件
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" />
回到类,开启定位图层,配置定位参数
// 定位
ImageButton ibLocal;
LocationClient mLocClient;
public MyLocationListenner myListener;
boolean isFirstLoc = true; // 是否首次定位
// 开启定位图层
mBaiduMap.setMyLocationEnabled(true);
// 定位初始化
mLocClient = new LocationClient(this);
myListener = new MyLocationListenner();
mLocClient.registerLocationListener(myListener);
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系
option.setScanSpan(3000);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
option.setOpenGps(true);//可选,默认false,设置是否使用gps
mLocClient.setLocOption(option);
定位监听函数
public class MyLocationListenner 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(100)
.latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
// 设置定位数据
mBaiduMap.setMyLocationData(locData);
// 获取经纬度、地址信息
Latitude = location.getLatitude();
Longitude = location.getLongitude();
address = location.getAddrStr();
Log.i(TAG, "Lantitude:" + Latitude + ",Longitude:" + Longitude);
if (isFirstLoc) {
isFirstLoc = false;
showLoc();
}
}
}
定位按钮点击事件
if (!mLocClient.isStarted()) {
mLocClient.start();
}
if (!isFirstLoc) {
showLoc();
}
为了每次点击按钮的时候,将地图拉回到当前位置,定义了一个Boolean变量isFirstLoc对showLoc()方法进行调用,感觉这样写有点蠢
private void showLoc() {
// 在地图上显示当前坐标
LatLng ll = new LatLng(Latitude,
Longitude);
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
Toast.makeText(MapActivity.this, "地址:" + address, Toast.LENGTH_SHORT).show();
}
退出地图的时候要记得销毁定位
@Override
protected void onDestroy() {
super.onDestroy();
// 在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
// 退出时销毁定位
if (mLocClient != null && mLocClient.isStarted()) {
mLocClient.unRegisterLocationListener(myListener);
mLocClient.stop();
mLocClient = null;
}
// 关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
}
地图标记/覆盖物
// 覆盖物
private BitmapDescriptor mMaker;
// 设置覆盖物图标
mMaker = BitmapDescriptorFactory.fromResource(R.drawable.maker);
// 设置地图的点击事件
mBaiduMap.setOnMapClickListener(new MyOnMapClickListener());
public class MyOnMapClickListener implements BaiduMap.OnMapClickListener {
@Override
public void onMapClick(LatLng latLng) {
mLocClient.stop();// 停止定位
mBaiduMap.clear();// 清除图层
//获取覆盖物经纬度
Latitude = latLng.latitude;
Longitude = latLng.longitude;
// 定义Maker坐标点
LatLng point = new LatLng(Latitude, Longitude);
// 构建MarkerOption,用于在地图上添加Marker
MarkerOptions options = new MarkerOptions().position(point).icon(mMaker);
// 在地图上添加Marker,并显示
mBaiduMap.addOverlay(options);
// 创建地理编码检索实例
GeoCoder geoCoder = GeoCoder.newInstance();
// 设置地理编码检索监听
geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
if (geoCodeResult == null || geoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
// 没有检测到结果
}
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
if (reverseGeoCodeResult == null || reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(MapActivity.this, "抱歉,未能找到结果", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MapActivity.this, "位置:" + reverseGeoCodeResult.getAddress(), Toast.LENGTH_LONG).show();
}
}
});
// 设置反地理编码位置坐标
geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
return false;
}
}
检索
界面增加一个输入框和搜索图标,输入检索内容后,点击搜索图标弹出一个相关地址内容列表,选中一个地址,地图定位到该地址
// 检索
private PoiSearch mPoiSearch;
private EditText etSearch;
private ImageButton ibSearch;
实例化mPoiSearch,添加监听事件
// 创建检索实例及监听
mPoiSearch = PoiSearch.newInstance();
mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {
@Override
public void onGetPoiResult(PoiResult poiResult) {
// 获取POI检索结果
}
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
// 获取Place详情页检索结果
Log.i(TAG, "=====PoiDetailResult====" + poiDetailResult);
}
@Override
public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
// 获取POI室内检索结果
}
});
添加搜索按钮的点击事件,这里先以“长沙”为例展示搜索功能,后面再写动态当前城市获取,关键字就是搜索内容,这里返回的是一个Boolean值,可以打印看看
case R.id.btn_search:
if (!"".equals(etSearch.getText().toString())) {
boolean isSearch = mPoiSearch.searchInCity((new PoiCitySearchOption())
.city("长沙").keyword(etSearch.getText().toString()));
Log.i(TAG, "====isSearch====" + isSearch);
} else {
Toast.makeText(MapActivity.this, "请输入搜索内容", Toast.LENGTH_LONG).show();
}
break;
检索成功弹出相关地址内容列表,使用popupwindows
private PopupWindow popupWindow;
private ListView mListView;
ArrayList<HashMap<String, String>> data_search = new ArrayList<HashMap<String, String>>();
private void getPopupWindow() {
if (null != popupWindow) {
popupWindow.dismiss();
return;
} else {
initPopupWindow();
}
}
protected void initPopupWindow() {
View popupWindow_view = getLayoutInflater().inflate(R.layout.popup_windows, null,
false);
popupWindow = new PopupWindow(popupWindow_view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
mListView = (ListView) popupWindow_view.findViewById(R.id.lv_search);
SimpleAdapter simple = new SimpleAdapter(MapActivity.this,
data_search,
R.layout.item_search,
new String[]{"address"},
new int[]{R.id.tv_name});
mListView.setAdapter(simple);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListView.getItemAtPosition(position);
// 定点坐标
Latitude = Double.parseDouble(data_search.get(position).get("latitude"));
Longitude = Double.parseDouble(data_search.get(position).get("longitude"));
// 定义Maker坐标点
LatLng point = new LatLng(Latitude, Longitude);
// 构建MarkerOption,用于在地图上添加Marker
MarkerOptions options = new MarkerOptions().position(point).icon(mMaker);
// 在地图上添加Marker,并显示
mBaiduMap.addOverlay(options);
// 把地图定位到该坐标
LatLng ll = new LatLng(Latitude,Longitude);
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
popupWindow.dismiss();
popupWindow = null;
}
});
popupWindow_view.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
popupWindow = null;
}
return false;
}
});
}
监听事件获取POI检索结果
@Override
public void onGetPoiResult(PoiResult poiResult) {
// 获取POI检索结果
if (poiResult.error != SearchResult.ERRORNO.NO_ERROR) { // 详情检索失败
// result.error请参考SearchResult.ERRORNO
Toast.makeText(MapActivity.this, poiResult.error.toString(), Toast.LENGTH_LONG).show();
} else {// 检索成功
data_search.clear();
//遍历所有POI
for (PoiInfo poi : poiResult.getAllPoi()) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("address", poi.address);
map.put("latitude", poi.location.latitude + "");
map.put("longitude", poi.location.longitude + "");
data_search.add(map);
Log.i(TAG, "=====onGetPoiResult====" + poi.address + poi.location.latitude + "===" + poi.location.longitude);
}
getPopupWindow();
popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.CENTER, 0, 0);
}
}
最后用完别忘记销毁
mPoiSearch.destroy();
效果图:
动态城市获取
实现当前位置跟随地图拖拽实时更新,发现了一个地图状态改变相关接口 BaiduMap.OnMapStatusChangeListener
BaiduMap.OnMapStatusChangeListener statusListener = new BaiduMap.OnMapStatusChangeListener() {
LatLng startLng, finishLng;
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
startLng = mapStatus.target;// 开始时,地图操作的中心点
Log.i(TAG, "=====onMapStatusChangeStart=====");
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
Log.i(TAG, "=====onMapStatusChange=====");
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
finishLng = mapStatus.target;// 结束时,地图操作的中心点
if (startLng.latitude != finishLng.latitude
|| startLng.longitude != finishLng.longitude) {
// 两相比较不等,证明地图发生移动,此处获得最新位置信息
}
}
};
// 设置地图状态改变监听
mBaiduMap.setOnMapStatusChangeListener(statusListener);
接下来就是根据经纬度反编码得到位置详细信息,与前面地图点击事件代码相似
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
// 滑动搜索
finishLng = mapStatus.target;
if (startLng.latitude != finishLng.latitude
|| startLng.longitude != finishLng.longitude) {
LatLng latLng = new LatLng(finishLng.latitude,
finishLng.longitude);
// 创建地理编码检索实例
GeoCoder geoCoder = GeoCoder.newInstance();
// 设置地理编码检索监听
geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
if (geoCodeResult == null || geoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
// 没有检测到结果
}
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
if (reverseGeoCodeResult == null || reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(MapActivity.this, "抱歉,未能找到结果", Toast.LENGTH_LONG).show();
} else {
currCity= reverseGeoCodeResult.getAddressDetail().city;
tvCity.setText(currCity);
}
}
});
// 设置反地理编码位置坐标
geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(latLng));// 这句一定要放监听事件后面!
}
}
拖动地图,注意左上角城市变化: