百度地图 sdk 开发(1)

参考:

Android Studio 百度地图开发http://blog.csdn.net/u012005313/article/details/48580229


陆陆续续接触了百度地图的开发,官网上的资料以及 sample 都还比较详细,不过内容较多,也比较复杂,并不是全部的功能都有讲解,所以每次重新接触都需要花费一段时间学习。这次,将关于百度地图 sdk 开发的步骤记录下来,方便下次使用


主要内容

  1. 地图开发浅析
  2. 申请密匙
  3. 编译官方 demo
  4. Hello BaiduMap 的实现
  5. 地图类型与缩放级别
  6. 地图控制
  7. 地图手势
  8. 标注覆盖物
  9. 弹出窗覆盖物

地图开发浅析

不同的地图采用不同的坐标系,手机使用的 GPS 全球卫星定位系统采用 WGS84 坐标系,百度地图采用坐标系为 BD09

百度地图坐标查找系统:百度地图 拾取坐标系统

Note:百度地图坐标查找系统查找到的坐标属于 BD09 坐标系,不同坐标系之间的坐标需要经过转换才能正确使用


申请密匙

使用百度地图 sdk 之前需要申请开发密匙,密匙申请地址:
http://lbsyun.baidu.com/apiconsole/key

申请百度地图 Android SDK 密匙的官网教程:
申请密钥Android SDK

里面的讲解很详细,这里记录下如何获取 Android 签名证书的 SHA1 值:

  • 打开控制台窗口,进入 .android 目录(当前开发环境为 win7.android 文件夹在 c:\Users\Lenovo\

  • 输入命令

    keytool -list -v -keystore debug.keystore

    输入密匙口令(默认为 android),即在窗口中打印出 SHA1 码:

    如果想要把打印出的值放入文本中,方便操作,可以使用下面的命令

    keytool -list -v -keystore debug.keystore > sha1.txt

    在当前目录下找到 sha1.txt,打开可以找到 SHA1


编译官方 demo

就像上面说的,使用百度地图 sdk 必须申请密匙,编译百度提供的 Demo 的时候,就遇到了关于开发密匙的问题

下载,打开 demo 工程,发现并没有开发密匙,那就按照上面的教程找到 SHA1 值和包名,申请得到开发密匙后,编译运行,发现 key验证错误

在网上找到解决方法:
百度地图Key验证失败230错误

其实是自己没有仔细查找,依葫芦画瓢就使用了 keytool 命令,百度官方 demo 已经包含了 debug.keystore,所以不需要使用本地默认的 debug.keystore,使用 demo 里包含的 debug.keystore 即可

Note:在日志中,百度地图也给了解决方法链接:http://bbs.lbsyun.baidu.com/forum.php?mod=viewthread&tid=106461


Hello BaiduMap 的实现

官网文档有一个关于如何使用 sdk ,以及如何使用百度地图控件实现一个最简单的地图显示的教程,里面有基于 eclipseandroid studio 的配置,我使用的是 android studio,所以接下来使用 android studio 构建一个百度地图的 BaiduMap Demo

  • 下载 sdk

百度地图 Android sdk 下载地址:
相关下载Android地图SDK

Note:实际开发过程中,可结合需求下载,以减小 sdk 大小

  • 配置 sdk

新建 Android Studio 工程,将解压后的 sdk 中的 .jar 文件放入 app -> libs 文件夹中,对每个jar文件,右键-选择 Add As Library,导入到工程中。在 app -> src -> main 路径下新建文件夹 jniLibs,将 .so 文件放入其中

Note:.so 文件可能会按不同 CPU 架构分类,将整个文件夹放入 jniLibs

我选择了全部功能的 sdk 包,可实现功能如下:

Note:下载解压后发现还包含了一个 assets 文件夹,可以将这个放入 app -> main 路径下

  • 配置开发密匙

获取 SHA1 值和包名,申请开发密匙

app -> src -> AndroidMaifest.xml 中,加入:

<application>  
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="开发者 key" />  
</application>

value 部分替换为开发密匙

  • 配置使用权限

app -> src -> AndroidManifest.xml 中,加入:

<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" />
  • 初始化 sdk

在初始化地图组件前初始化地图 sdk

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);   
    //在使用SDK各组件之前初始化context信息,传入ApplicationContext  
    //注意该方法要再setContentView方法之前实现  
    SDKInitializer.initialize(getApplicationContext());  
    setContentView(R.layout.activity_main);  
}  

由于需要在多个 activity 中使用地图,所以将初始化方法放在 Application 中进行,新建文件夹 App,继承自 Application

public class App extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        SDKInitializer.initialize(getApplicationContext());
    }
}

修改 AndroidManifest.xml 中的 Application 为自定义的 App:

   <application
        ...
        android:name=".App"
        ...
        ...>
    </application>
  • 使用地图控件

地图控件为 MapView,在 xml 文件中加入:

<com.baidu.mapapi.map.MapView
    android:id="@+id/map_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

在使用地图控件过程中,需要显式设置生命周期管理,修改如下:

public class HelloActivity extends AppCompatActivity {

    private MapView mapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hello);

        mapView = (MapView) findViewById(R.id.map_view);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }
}

编译,安装,运行,成功:


地图类型与缩放级别

地图类型

百度地图 Android SDK 提供了 3 种类型的地图资源:普通矢量地图、卫星图和空白地图

从地图控件 MapView 中获取地图 BaiduMap

BaiduMap baiduMap = mapView.getMap();

设置地图类型 setMapType:

//普通地图  
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);  

//卫星地图  
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);  

//空白地图, 基础地图瓦片将不会被渲染。在地图类型中设置为NONE,将不会使用流量下载基础地图瓦片图层。使用场景:与瓦片图层一起使用,节省流量,提升自定义瓦片图下载速度。
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);

通过 mBaiduMap.getMapType 获取地图当前类型

实时交通图 和 城市热力图

没有用到过,不过在官网教程上有介绍,记录一下

和设置地图类型类似,获取 BaiduMap

开启交通图:

//开启交通图   
mBaiduMap.setTrafficEnabled(true);

开启热力图:

//开启热力图   
mBaiduMap.setBaiduHeatMapEnabled(true);
  • 实时交通图和城市热力图的设置与地图类型无关,就是哪种地图类型都可以开启这两种类型
  • 实时交通图和城市热力图并不互斥,可以同时开启

通过函数 mBaiduMap.isSupportBaiduHeatMap 查询当前图区是否支持百度热力图

通过函数 mBaiduMap.setTrafficEnabled 查询是否已打开交通图

缩放级别

百度地图缩放级别为 3 - 21 级,级数越高,精度越高

V3.7.0起,地图支持缩放至21级缩放显示;卫星图、热力图和交通路况图最高支持20级缩放显示。 在打开21级地图切换卫星图、热力图和交通路况图,地图层级会自动缩放到20级。

也就是说,现在开发的 Android 百度地图的使用缩放最高就是 21 级了,其中卫星图、热力图和交通路况图只能缩放到 20

查询最大最小缩放级别

获取 BaiduMap 后,可以查询最大最小缩放级别:

float maxZoom = baiduMap.getMaxZoomLevel();
float minZoom = baiduMap.getMinZoomLevel();
Log.e(TAG, "onCreate: minZoom = " + minZoom + " maxZoom = " + maxZoom);

打印出来是 [3 - 22]

onCreate: minZoom = 3.0 maxZoom = 22.0

Note:在实际使用中,真的只能缩放到 21 级,可以是百度没改好吧

查询当前缩放级别

刚开始加载地图,获取到 BaiduMap 后,可以获取 地图状态类 MapStatus,其包含了当前缩放级别:

MapStatus mapStatus = baiduMap.getMapStatus();
currentZoom = mapStatus.zoom;
Log.e(TAG, "onCreate: currentZoom = " + currentZoom);

在实际运行过程中,可以通过 地图绘制回调接口 BaiduMap.OnMapDrawFrameCallback 获取当前缩放级别:

baiduMap.setOnMapDrawFrameCallback(new BaiduMap.OnMapDrawFrameCallback() {
    @Override
    public void onMapDrawFrame(GL10 gl10, MapStatus mapStatus) {

    }

    @Override
    public void onMapDrawFrame(MapStatus mapStatus) {
        currentZoom = mapStatus.zoom;
    }
});

如果要使用当前缩放级别,可以在 地图渲染完成回调接口 BaiduMap.OnMapRenderCallback 中进行操作:

baiduMap.setOnMapRenderCallbadk(new BaiduMap.OnMapRenderCallback() {
    @Override
    public void onMapRenderFinished() {
        Log.e(TAG, "onMapRenderFinished: currentZoom = " + currentZoom);
    }
});

地图控制

百度地图除了显示地图信息外,还会显示地图 logo、指南针以及比例尺,以及缩放控件

默认在左下角显示,不可删除

Logo 位置保存为一个枚举类 LogoPosition

package com.baidu.mapapi.map;

public enum LogoPosition {
    logoPostionleftBottom,
    logoPostionleftTop,
    logoPostionCenterBottom,
    logoPostionCenterTop,
    logoPostionRightBottom,
    logoPostionRightTop;

    private LogoPosition() {
    }
}

通过 mapView.getLogoPosition() 获取当前 Logo 位置

通过 mapView.setLogoPosition() 设置 Logo 位置

比例尺

通过 mapView.showScaleControl() 设置是否显示比例尺

通过 mapView.getMapLevel() 获取当前地图级别对应比例尺大小

通过 mapView.getScaleControlViewHeight() 获取比例尺高度

通过 mapView.getScaleControlViewWidth() 获取比例尺宽度

缩放控件

通过 mapView.showZoomControls() 设置是否显示缩放控件

通过上一节介绍的方法获取缩放级别

通过设置 baiduMap.setMaxAndMinZoomLevel 设置地图支持的最大最小缩放级别,取值范围为 [3, 21]:

public final void setMaxAndMinZoomLevel(float max, float min)

设置地图最大以及最小缩放级别,地图支持的最大最小级别分别为[3-21]

参数:

max - [3-21] 且 max > min, 否则无效

min - [3-21] 且 max > min, 否则无效


地图手势

百度地图同样提供了多种手势操作,包括平移,缩放,俯视(3D),旋转,是否设置指南针

首先获取地图控件 MapView

MapView mapView = (MapView) findViewById(R.id.map_view);

接着获取百度地图 BaiduMap

BaiduMap baiduMap = mapView.getMap();

最后获取百度地图 UI 控制器 UiSettings

UiSettings uiSettings = baiduMap.getUiSettings();

在百度地图 UI 控制器 UiSettings 中可以进行上述手势操作的查询与设置。

同时 UiSettings 在含有是否允许所有手势操作功能:

public void setAllGesturesEnabled(boolean enabled)

设置是否允许所有手势操作

参数:

enabled - 是否允许所有手势操作


标注覆盖物

可以在百度地图设定标注物

图像标注

利用图像进行标注

单个标注

假定标注浙江理工大学(坐标:120.359669,30.319648

  • 首先获取 MapView 控件以及百度地图 BaiduMap

    MapView mapView = (MapView) findViewById(R.id.map_view);
    BaiduMap baiduMap = mapView.getMap();
    
  • 接下来改变地图状态,将地图中心转到浙江理工大学:

    // 新建一个坐标点
    LatLng latLng = new LatLng(30.319648, 120.359669);
    // 设置地图新中心点
    MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng);
    // 改变地图状态
    baiduMap.setMapStatus(mapStatusUpdate);
    

    Note:也可以在设置地图新中心点的同时改变缩放级别,以便更清晰的查看结果,修改如下:

    MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLngZoom(latLng, 16.0f);
    //MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng);
    
  • 最后创建图像覆盖物并加载到地图上:

    // 创建图标
    BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ic_marker);
    // 创建覆盖物
    OverlayOptions overlayOptions = new MarkerOptions()
            .position(latLng)
            .icon(bitmapDescriptor);
    // 向地图添加一个 Overlay
    baiduMap.addOverlay(overlayOptions);
    

Note:对于 BitmapDescriptor 而言,不再需要使用后,及时调用 recycle 函数,回收 bitmap 资源

多个标注

可以一次性载入多个图标,将创建的多个 MarkerOptions 整合为列表,调用函数 baiduMap.addOverlays() 载入即可:

// 120.359669,30.319648 浙江理工大学
// 120.359629,30.327168 杭州职业技术学院
// 120.356678,30.31653 杭州地铁文泽路

List<LatLng> latLngList = new ArrayList<>();

LatLng point1 = new LatLng(30.319648, 120.359669);
LatLng point2 = new LatLng(30.327168, 120.359629);
LatLng point3 = new LatLng(30.31653, 120.356678);

latLngList.add(point1);
latLngList.add(point2);
latLngList.add(point3);

BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ic_marker);

List<OverlayOptions> overlayOptionsList = new ArrayList<>();
for (LatLng latLng : latLngList) {
    OverlayOptions overlayOptions = new MarkerOptions()
            .position(latLng)
            .icon(bitmapDescriptor);

    overlayOptionsList.add(overlayOptions);
}

baiduMap.addOverlays(overlayOptionsList);

Note:清除单个 Marker 可以使用

Note:调用 BaiduMap.clear() 可以清空地图所有的 Overlay 覆盖物以及 InfoWindow

图像覆盖物额外功能

图像覆盖物 MarkerOptions 还可以设定标题,添加额外信息

LatLng latLng = new LatLng(30.319648, 120.359669);

BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ic_marker);

Bundle bundle = new Bundle();
bundle.putString("extra", "Hello World");

OverlayOptions overlayOptions = new MarkerOptions()
        .title("浙江理工大学")
        .extraInfo(bundle)
        .position(latLng)
        .icon(bitmapDescriptor);

baiduMap.addOverlay(overlayOptions);

百度地图 BaiduMap 需要实现地图 Marker 覆盖物点击事件监听接口 BaiduMap.OnMarkerClickListener,将该 Marker 的信息提取出来,包括标注坐标,标题,额外信息:

baiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
    @Override
    public boolean onMarkerClick(Marker marker) {
        LatLng point = marker.getPosition();
        Log.e(TAG, "onMarkerClick: " + point.toString());

        String title = marker.getTitle();
        Log.e(TAG, "onMarkerClick: title = " + title);

        Bundle bundle = marker.getExtraInfo();
        String extraInfo = bundle.getString("extra");
        Log.e(TAG, "onMarkerClick: extra = " + extraInfo);

        return false;
    }
});

Note:可以设定 Marker 是否可显示

public boolean isVisible()
获取 marker 覆盖物的可见性

public MarkerOptions visible(boolean visible)
设置 marker 覆盖物的可见性

关于标注覆盖物拖拽

在百度地图 Android SDK 教程中说明标注覆盖物可拖拽,同时也设置了拖拽监听接口,不过我试了一下好像没有效果,等待日后解决


弹出窗覆盖物

有时希望在设置覆盖物的同时显示一些文字信息,比如该地点的名称等,可以使用百度地图提供了弹出窗覆盖物 InfoWindow 实现

InfoWindow 提供了两个构造器:

InfoWindow(BitmapDescriptor bd, LatLng position, int yOffset, InfoWindow.OnInfoWindowClickListener listener)
通过传入的 bitmap descriptor 构造一个 InfoWindow。
InfoWindow(View view, LatLng position, int yOffset)
通过传入的 view 构造一个 InfoWindow, 此时只是利用该view生成一个Bitmap绘制在地图中,监听事件由开发者实现。

Note:BitmapDescriptor 可以通过 BitmapDescriptorFactory.fromView(view) 得到

InfoWindow 同时包含一个信息窗口点击事件监听接口 InfoWindow.OnInfoWindowClickListener,用于信息窗口点击事件处理,可在构造器中传入

如上面所示,在地图上标注浙江理工大学:

LatLng latLng = new LatLng(30.319648, 120.359669);

BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.mipmap.ic_marker);

Bundle bundle = new Bundle();
bundle.putString("extra", "Hello World");

OverlayOptions overlayOptions = new MarkerOptions()
        .title("浙江理工大学")
        .extraInfo(bundle)
        .position(latLng)
        .draggable(true)
        .zIndex(16)
        .icon(bitmapDescriptor);

baiduMap.addOverlay(overlayOptions);

addInfoWindow();

同时增加 InfoWindow,显示浙江理工大学校名:

LatLng latLng = new LatLng(30.319648, 120.359669);
//创建InfoWindow展示的view
final Button button = new Button(getApplicationContext());
button.setText("浙江理工大学");
button.setBackgroundResource(R.drawable.popup);

InfoWindow.OnInfoWindowClickListener listener = new InfoWindow.OnInfoWindowClickListener() {
    @Override
    public void onInfoWindowClick() {
        baiduMap.hideInfoWindow();
    }
};

//创建InfoWindow , 传入 view, 地理坐标, y 轴偏移量
InfoWindow mInfoWindow = new InfoWindow(BitmapDescriptorFactory.fromView(button), latLng, -47, listener);
//显示InfoWindow
baiduMap.showInfoWindow(mInfoWindow);

实现效果:点击 InfoWindow 后消失

Note:可以在 Marker 的点击事件中设定 InfoWindow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值