soapgu/PlayPen

Baidu地图安卓SDK使用

soapgu opened this issue · 0 comments

  • 配置及初始化

  1. 注册百度账号
  2. 申请api key
    这里申请需要填写SHA1 和 package name。
    和语音识别api认证差不多,需要用到
    gradle signingReport 命令

图片

3. 设置manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 访问网络,进行地图相关业务数据请求,包括地图数据,路线规划,POI检索等 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 获取网络状态,根据网络状态切换进行数据请求网络转换 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- 读取外置存储。如果开发者使用了so动态加载功能并且把so文件放在了外置存储区域,则需要申请该权限,否则不需要 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 写外置存储。如果开发者使用了离线地图,并且数据写在外置存储区域,则需要申请该权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MapforBaidu"
        tools:targetApi="31">
        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="ykHFKEKef1oLj79NDWMR4NqDykVvL7CW" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>
</manifest>

需要设置四个权限、自定义application以及meta-data的API_KEY

  1. 设置sdk依赖

implementation 'com.baidu.lbsyun:BaiduMapSDK_Map:7.5.4'
选用最简单的。

  1. 自定义Application实现
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        SDKInitializer.initialize(this);
        SDKInitializer.setCoordType(CoordType.BD09LL);
    }
}

按照文档直接抄代码需要初始化SDK

然鹅报错了

 Caused by: com.baidu.mapapi.common.BaiduMapSDKException: not agree privacyMode, please invoke SDKInitializer.setAgreePrivacy(Context, boolean) function
                                                                                                    	at com.baidu.mapsdkplatform.comapi.a.d(BMapManagerInternal.java:37)
                                                                                                    	at com.baidu.mapsdkplatform.comapi.Initializer.initialize(Initializer.java:33)
                                                                                                    	at com.baidu.mapapi.SDKInitializer.initialize(SDKInitializer.java:1)
                                                                                                    	at com.demo.mapforbaidu.MyApplication.onCreate(MyApplication.java:12)
                                                                                                    	at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1202)
  • SDK注意事项
    这里设置privacyMode是必填项。
    抄代码还不行,SDKInitializer.setAgreePrivacy(this, false);还是报错!一定要设SDKInitializer.setAgreePrivacy(this, true);
    百度怎么想的,既然设置false不能用sdk,为啥开放出来设置一次?

图片

  • 添加地图控件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.baidu.mapapi.map.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:focusable="true"/>

</androidx.constraintlayout.widget.ConstraintLayout>
public class MainActivity extends AppCompatActivity {
    private MapView mMapView = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.mMapView = findViewById(R.id.mapView);
    }

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

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

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

图片

  • 初始位置以及地图类型设置

看前面截图总感觉哪里怪怪的!
对哦,我也不在皇城脚下啊。
SDK一般常规操作是定位到当前位置

不过我觉得这样代价其实蛮高的,需要获取定位权限。如果我只是要看某一个位置地图哪?

首先通过拾取坐标工具,找出要显示位置的经度纬度

图片

@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       this.mMapView = findViewById(R.id.mapView);
       LatLng centerPoint = new LatLng(31.170474,121.401209);
       MapStatus mapStatus = new MapStatus.Builder().target(centerPoint).zoom(18).build();
       MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus);
       BaiduMap map = this.mMapView.getMap();
       map.setMapStatus(mapStatusUpdate);
       map.setMapType(BaiduMap.MAP_TYPE_NORMAL);
   }

利用API的BaiduMap对象来设置,还是比较简单的
图片
现在顺眼多了吧

  • 绘制点标记

       //定义Maker坐标点
        LatLng point = new LatLng(31.170503, 121.402091);
        //构建Marker图标
        BitmapDescriptor bitmap = BitmapDescriptorFactory
                .fromResource(R.drawable.mark);
        //构建MarkerOption,用于在地图上添加Marker
        OverlayOptions option = new MarkerOptions()
                .position(point)
                .icon(bitmap);
       //在地图上添加Marker,并显示
        this.mMapView.getMap().addOverlay(option);

图标可以完全自定义
比较遗憾的是MarkerOption的title方法已经deprecated了,调用了也没作用

可替代方案是再在个TextOptions

OverlayOptions mTextOptions = new TextOptions()
                .text("我的起点") //文字内容
                //.bgColor(0xAAFFFF00) //背景色
                .fontSize(24) //字号
                .fontColor(0xFF000000) //文字颜色
                .position(point);

this.mMapView.getMap().addOverlay(mTextOptions);

图片

  • 一些高级功能的尝试

  • 鸟瞰图
    其实地图是支持3D的
    把MapStatus的overlook这个api设一个俯视角度就行

  • 小小挫折

一开始我想要拿到所在坐标的3D建筑模型,百度其实基本为所有的建筑物都建模了,有现成的东西为啥还要自己画
结果发现API缺依赖,加了 implementation 'com.baidu.lbsyun:BaiduMapSDK_Search:7.5.4'
首先这个api不能在onCreate调用。
后面发现账号权限不够
图片

  • 绘制3D棱柱

好了只能“手工”画了
private void renderPrism(){
List locations = new ArrayList<>();
locations.add(new LatLng(31.170561,121.40181));
locations.add(new LatLng(31.170642,121.402066));
locations.add(new LatLng(31.170437,121.402156));
locations.add(new LatLng(31.170352,121.401905));

    PrismOptions prismOptions = new PrismOptions();
    prismOptions.setHeight(20);
    prismOptions.setPoints(locations);
    prismOptions.setSideFaceColor(0xAAFF0000);
    prismOptions.setTopFaceColor(0xAA00FF00);
    // 控制3D建筑物单体动画
    prismOptions.setAnimation(true);
    // 设置3D建筑物开始显示层级
    prismOptions.setShowLevel(4);
    mMapView.getMap().addOverlay(prismOptions);
}

图片

  • 3DMarker

看起来差不多了,但是标记跑到下面去了
为了和3D棱柱配合使用只能使用3DMarker了

        Projection projection = this.mMapView.getMap().getProjection();
        LatLng point = new LatLng(31.170503, 121.402091);
        Point srcPoint = projection.geoPoint3toScreenLocation(point, 20);
        LatLng latLng = projection.fromScreenLocation(srcPoint);

加上投影转换,这些差不多了吧。结果projection是空的,应该是地图还没加载的关系。需要调整下调用时机
一开始在setOnMapDrawFrameCallback的回调后使用发觉没用,最后还是用OnMapLoadedCallback

map.setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
           @Override
           public void onMapLoaded() {
                render3DMarkPoint();
           }
        });

图片

  • 参考链接

完结撒花