在Android应用中,很多时候需要地图功能,回顾过去写的项目和百度地图api,开始总结一下Android百度地图的实现。首先总结一下怎么开始一个Android百度地图功能。
当使用百度地图的时候,提到一个appkey。“在使用百度地图SDK为您提供的各种LBS能力之前,您需要获取百度地图移动版的开发密钥,该密钥与您的百度账户相关联。因此,您必须先有百度帐户,才能获得开发密钥。并且,该密钥与您创建的过程名称有关。Key地址为:http://lbsyun.baidu.com/apiconsole/key”
这是百度地图api给的定义。总之,一个项目包名和sha1对应一个appkey。首先注册百度账号,根据教程一步步创建appkey。
当有了appkey,我们就能开一部署一个android百度地图环境。首先在百度api的相关下载中,将需要的功能勾选上,并下载相关的开发包,示例代码等。将开发包导入项目libs文件夹下。然后,开始部署AndroidMinifest.xml,添加权限,添加appkey,定位的service。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="自己的包名"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<!-- 百度地图权限 -->
<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.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 访问网络,网络定位需要上网 -->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="申请的appkey" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" >
<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>
</application>
</manifest>
下一步就是在activity_main.xml中添加布局文件。本片文章还有自定义的放大缩小,定位等功能。
<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" >
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<ImageButton
android:id="@+id/ib_small"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/small"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginBottom="60dp"/>
<ImageButton
android:id="@+id/ib_large"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_above="@+id/ib_small"
android:layout_alignLeft="@+id/ib_small"
android:background="@drawable/large" />
<ImageButton
android:id="@+id/ib_mode"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_above="@+id/ib_large"
android:layout_alignLeft="@+id/ib_large"
android:layout_marginBottom="12dp"
android:background="@drawable/mode" />
<ImageButton
android:id="@+id/ib_traffic"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_above="@+id/ib_loc"
android:layout_alignLeft="@+id/ib_loc"
android:layout_marginBottom="12dp"
android:background="@drawable/offtraffic" />
<ImageButton
android:id="@+id/ib_loc"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_alignTop="@+id/ib_small"
android:layout_marginLeft="10dp"
android:background="@drawable/loc" />
</RelativeLayout>
显示效果图:
下面开始具体的代码实现
当前程序有三个功能:显示地图,显示定位,实现按钮控制。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
//初始化控件
initView();
//初始化地图
initMap();
//定位
initLocation();
}
一。显示基本地图
初始化地图显示,将地图在手机上显示出来
//获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
// 不显示缩放比例尺
mMapView.showZoomControls(false);
// 不显示百度地图Logo
mMapView.removeViewAt(1);
//百度地图
mBaiduMap = mMapView.getMap();
// 改变地图状态,使地图显示在恰当的缩放大小
MapStatus mMapStatus = new MapStatus.Builder().zoom(15).build();
MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
mBaiduMap.setMapStatus(mMapStatusUpdate);
二。地图的控制按钮:缩放按钮,切换模式按钮,开启实时交通图
1.在地图初始化显示时,我将自带的缩放比例尺去掉了,需要自定义一个缩放按钮。
我们一般显示将地图显示在5-18级别中,所以在点击事件中对按钮进行了控制。
case R.id.ib_large:
if (zoomLevel < 18) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomIn());
ib_small.setEnabled(true);
} else {
showInfo("已经放至最大,可继续滑动操作");
ib_large.setEnabled(false);
}
break;
case R.id.ib_small:
if (zoomLevel > 6) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomOut());
ib_large.setEnabled(true);
} else {
ib_small.setEnabled(false);
showInfo("已经缩至最小,可继续滑动操作");
}
break;
zoomlevel是一个全局变量,这时候就需要实时监控地图的缩放级别是多少,需要给地图添加一个地图状态改变的监听事件
//设置地图状态改变监听器
mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus arg0) {
}
@Override
public void onMapStatusChangeFinish(MapStatus arg0) {
}
@Override
public void onMapStatusChange(MapStatus arg0) {
//当地图状态改变的时候,获取放大级别
zoomLevel = arg0.zoom;
}
});
2.切换显示模式和实时交通图
boolean modeFlag = true;//设置初始时是普通模式
case R.id.ib_mode://卫星模式和普通模式
if(modeFlag){
modeFlag = false;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
showInfo("开启卫星模式");
}else{
modeFlag = true;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
showInfo("开启普通模式");
}
break;
case R.id.ib_traffic://是否开启交通图
if(mBaiduMap.isTrafficEnabled()){//判断是否开启了交通图
mBaiduMap.setTrafficEnabled(false);
ib_traffic.setBackgroundResource(R.drawable.offtraffic);
showInfo("关闭实时交通图");
}else{
mBaiduMap.setTrafficEnabled(true);
ib_traffic.setBackgroundResource(R.drawable.ontraffic);
showInfo("开启实时交通图");
}
break;
三。定位自己
定位自己的思路是:当程序启动的时候,开启定位图层,开始定位,收到位置信息后将自己的位置显示在地图中间,当地图离开自己的位置时,点击定位自己的图标将地图重新显示自己的位置。
首先,开启定位图层,开始定位。
@Override
protected void onStart() {
super.onStart();
//开启定位
mBaiduMap.setMyLocationEnabled(true);
if(!mLocationClient.isStarted()){//如果定位client没有开启,开启定位
mLocationClient.start();
}
}
private void initLocation() {
//定位客户端的设置
mLocationClient = new LocationClient(this);
mLocationListener = new MyLocationListener();
//注册监听
mLocationClient.registerLocationListener(mLocationListener);
//配置定位
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");//坐标类型
option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
option.setOpenGps(true);//打开Gps
option.setScanSpan(1000);//1000毫秒定位一次
option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
mLocationClient.setLocOption(option);
}
//自定义的定位监听
private class MyLocationListener implements BDLocationListener{
@Override
public void onReceiveLocation(BDLocation location) {
//将获取的location信息给百度map
MyLocationData data = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
mBaiduMap.setMyLocationData(data);
if(isFirstLocation){
//获取经纬度
LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(ll);
//mBaiduMap.setMapStatus(status);//直接到中间
mBaiduMap.animateMapStatus(status);//动画的方式到中间
isFirstLocation = false;
showInfo("位置:" + location.getAddrStr());
}
}
}
注意,设置isFirstLocation=true,这样我们就只是开始的时候定位自己,并显示在地图中间,不会每一秒都跳一次。在我门需要定位的时候,将isFirstLocation重新设置成true就行。
case R.id.ib_loc:
isFirstLocation = true;
showInfo("返回自己位置");
break;
不要忘记在活动结束的时候,将定位取消
@Override
protected void onStop() {
super.onStop();
//关闭定位
mBaiduMap.setMyLocationEnabled(false);
if(mLocationClient.isStarted()){
mLocationClient.stop();
}
}
然后运行程序,发现一个带有定位功能,并能部分控制地图显示的app出来了,下面是MainActivity的源码
package 包名;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMapStatusChangeListener;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.Toast;
/**
* 我的百度地图首页
* @author jing__jie
*
*/
public class MainActivity extends Activity implements OnClickListener {
private MapView mMapView = null;
private BaiduMap mBaiduMap;
private ImageButton ib_large,ib_small,ib_mode,ib_loc,ib_traffic;
//模式切换,正常模式
private boolean modeFlag = true;
//当前地图缩放级别
private float zoomLevel;
//定位相关
private LocationClient mLocationClient;
private MyLocationListener mLocationListener;
//是否第一次定位,如果是第一次定位的话要将自己的位置显示在地图 中间
private boolean isFirstLocation = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
//初始化控件
initView();
//初始化地图
initMap();
//定位
initLocation();
}
private void initMap() {
//获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
// 不显示缩放比例尺
mMapView.showZoomControls(false);
// 不显示百度地图Logo
mMapView.removeViewAt(1);
//百度地图
mBaiduMap = mMapView.getMap();
// 改变地图状态
MapStatus mMapStatus = new MapStatus.Builder().zoom(15).build();
MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
mBaiduMap.setMapStatus(mMapStatusUpdate);
//设置地图状态改变监听器
mBaiduMap.setOnMapStatusChangeListener(new OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus arg0) {
}
@Override
public void onMapStatusChangeFinish(MapStatus arg0) {
}
@Override
public void onMapStatusChange(MapStatus arg0) {
//当地图状态改变的时候,获取放大级别
zoomLevel = arg0.zoom;
}
});
}
private void initLocation() {
//定位客户端的设置
mLocationClient = new LocationClient(this);
mLocationListener = new MyLocationListener();
//注册监听
mLocationClient.registerLocationListener(mLocationListener);
//配置定位
LocationClientOption option = new LocationClientOption();
option.setCoorType("bd09ll");//坐标类型
option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
option.setOpenGps(true);//打开Gps
option.setScanSpan(1000);//1000毫秒定位一次
option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
mLocationClient.setLocOption(option);
}
private void initView() {
//地图控制按钮
ib_large = (ImageButton)findViewById(R.id.ib_large);
ib_large.setOnClickListener(this);
ib_small = (ImageButton)findViewById(R.id.ib_small);
ib_small.setOnClickListener(this);
ib_mode = (ImageButton)findViewById(R.id.ib_mode);
ib_mode.setOnClickListener(this);
ib_loc = (ImageButton)findViewById(R.id.ib_loc);
ib_loc.setOnClickListener(this);
ib_traffic = (ImageButton)findViewById(R.id.ib_traffic);
ib_traffic.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ib_large:
if (zoomLevel < 18) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomIn());
ib_small.setEnabled(true);
} else {
showInfo("已经放至最大,可继续滑动操作");
ib_large.setEnabled(false);
}
break;
case R.id.ib_small:
if (zoomLevel > 6) {
mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomOut());
ib_large.setEnabled(true);
} else {
ib_small.setEnabled(false);
showInfo("已经缩至最小,可继续滑动操作");
}
break;
case R.id.ib_mode://卫星模式和普通模式
if(modeFlag){
modeFlag = false;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
showInfo("开启卫星模式");
}else{
modeFlag = true;
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
showInfo("开启普通模式");
}
break;
case R.id.ib_loc:
isFirstLocation = true;
showInfo("返回自己位置");
break;
case R.id.ib_traffic://是否开启交通图
if(mBaiduMap.isTrafficEnabled()){
mBaiduMap.setTrafficEnabled(false);
ib_traffic.setBackgroundResource(R.drawable.offtraffic);
showInfo("关闭实时交通图");
}else{
mBaiduMap.setTrafficEnabled(true);
ib_traffic.setBackgroundResource(R.drawable.ontraffic);
showInfo("开启实时交通图");
}
break;
default:
break;
}
}
@Override
protected void onStart() {
super.onStart();
//开启定位
mBaiduMap.setMyLocationEnabled(true);
if(!mLocationClient.isStarted()){
mLocationClient.start();
}
}
@Override
protected void onStop() {
super.onStop();
//关闭定位
mBaiduMap.setMyLocationEnabled(false);
if(mLocationClient.isStarted()){
mLocationClient.stop();
}
}
@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();
}
//显示消息
private void showInfo(String str){
Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
}
//自定义的定位监听
private class MyLocationListener implements BDLocationListener{
@Override
public void onReceiveLocation(BDLocation location) {
//将获取的location信息给百度map
MyLocationData data = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100)
.latitude(location.getLatitude())
.longitude(location.getLongitude())
.build();
mBaiduMap.setMyLocationData(data);
if(isFirstLocation){
//获取经纬度
LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
MapStatusUpdate status = MapStatusUpdateFactory.newLatLng(ll);
//mBaiduMap.setMapStatus(status);//直接到中间
mBaiduMap.animateMapStatus(status);//动画的方式到中间
isFirstLocation = false;
showInfo("位置:" + location.getAddrStr());
}
}
}
}
最后寄语,转载请注明出处,代码还要自敲,不要图快,一位的复制粘贴。