【安卓学习之常见问题】百度地图卫星地图精度不够

█ 【安卓学习之常见问题】百度地图卫星地图精度不够


█ 系列文章目录

提示:这里是收集了和文件分享有关的文章

█ 文章目录


█ 读前说明

  • 本文通过学习别人写demo,学习一些课件,参考一些博客,’学习相关知识,如果涉及侵权请告知
  • 本文只简单罗列相关的代码实现过程
  • 涉及到的逻辑以及说明也只是简单介绍,主要当做笔记,了解过程而已    

█ 问题

  • 精度不够,安卓百度地图,2D 3D最大2米,卫星最大10米;(从百度官网地app就可以看出)
  • >>>>高德卫星地图和百度卫星地图都是最大为10米; 天地图(有次数限制)、谷歌地图(不能直接访问) 放大级数很多。
level距离(米)level距离(米)
22:2;12:5000;
21:5;11:10000;
20:10;10:20000;
19:20;9:25000;
18:50;8:50000;
17:100;7:100000;
16:200;6:200000;
15:500;5:500000;
14:1000;4:1000000;
13:2000;3:2000000;
地图类型或图层显示层级地图类型或图层显示层级
2D地图4-21路况交通图11-21
3D地图19-21百度城市热力图11-21
卫星图4-20室内图17-22

█ 解决问题

  • 百度地图设置最大缩放级数
baiduMap.setMaxAndMinZoomLevel(33,8);
public class BaiduMap {
    private d j;// 地图状态、缩放等级等(因为混淆,所以不同版本的aar文件,打开不一定都是 d.class)
    /**
     * 修改百度地图的缩放级数
     */
    public final void setMaxAndMinZoomLevel(float max, float min) {
        if (!(max > 21.0F)) {
            if (!(min < 4.0F)) {
                if (!(max < min)) {
                    if (this.j != null) {
                        this.j.a(max, min);
                    }
                }
            }
        }
    }
}
package com.baidu.mapsdkplatform.comapi.map;
public class d implements com.baidu.mapsdkplatform.comjni.a.a.a {
    private static final String l = d.class.getSimpleName();
    public float a = 21.0F;
    public float b = 4.0F;
    public float c = 21.0F;
    /**
     * 修改百度地图的缩放级数 setMaxAndMinZoomLevel
     */
    public void a(float max, float min) {
        this.a = max;
        this.c = max;
        this.b = min;
        if (this.P != null) {
            this.P.setMaxAndMinZoomLevel(max, min);
        }

        if (this.i != null) {
            Bundle b = new Bundle();
            b.putInt("maxLevel", (int)max);
            b.putInt("minLevel", (int)min);
            this.i.setMaxAndMinZoomLevel(b);// nativeSetMaxAndMinZoomLevel(this.b, bundle);
        }
    }
}
  • 可以看出来被限制了最大最小值

█ 使用反射修改最大值

  • 使用反射修改最大值
		// 设置缩放等级 baiduMap.j.a(max, min);
        // baiduMap.setMaxAndMinZoomLevel(33,8);
        try {
            Class<?> mapClass = baiduMap.getClass();
            Field jField = mapClass.getDeclaredField("j");
            jField.setAccessible(true);
            d dObject = (d) jField.get(baiduMap);
            dObject.a(33.0f, 8.0f);
            Log.e("999", "当前级数1 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数1 出错==" + e.getMessage());
        }
  • 设置缩放监听
baiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus) {

            }

            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus, int i) {

            }

            @Override
            public void onMapStatusChange(MapStatus mapStatus) {

            }

            @Override
            public void onMapStatusChangeFinish(MapStatus mapStatus) {// 每次mapStatus地址都不一样
                Log.e("999", "onMapStatusChangeFinish=" + mapStatus.zoom + ",cur=" + baiduMap.getMapStatus().zoom + ",max=" + baiduMap.getMaxZoomLevel() + ",min=" + baiduMap.getMinZoomLevel());
            }
        });
  • 第一次测试效果:
2022-12-17 13:47:51.113 9088/com.xxx.debug E/999: 当前级数1 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 13:47:51.643 9088/com.xxx.debug E/999: onMapStatusChangeFinish=9.0,cur=9.0,max=20.0,min=8.0

>>>>发现刚开始设置最大放大级数为33,后面又变成了20

  • 发现在执行setMapType后会重新检查缩放级数:
package com.baidu.mapsdkplatform.comapi.map;
public class d implements com.baidu.mapsdkplatform.comjni.a.a.a {
    private static final String l = d.class.getSimpleName();
    public float a = 21.0F;
    public float b = 4.0F;
    public float c = 21.0F;
    AppBaseMap i;
    private MapController P = new MapController();
    /**
     * 检查缩放级数
     */
    private void T() {
        if (!this.q && !this.n && !this.m && !this.r) {// q=false,n=true(是否显示卫星地图),m=false,r=false
            this.a = this.c;
            if (this.P != null) {
                this.P.mMaxZoomLevel = this.a;
            }
        } else {
            if (this.a > 20.0F) {// a=33.0,b=8.0,c=33.0
                this.a = 20.0F;
                if (this.P != null) {// P.mMaxZoomLevel=33.0,P.mMinZoomLevel=8.0
                    this.P.mMaxZoomLevel = 20.0F;
                }
            }

            if (this.D().a > 20.0F) {// this.D().a = 12.0
                x mapStatusInner = this.D();// 地图状态的源数据
                mapStatusInner.a = 20.0F;
                this.a(mapStatusInner);
            }
        }
    }
    /**
     * 地图状态的源数据 x(SDK中用到的MapStatus也是从这里获取)
     * 将状态封装到Bundle中,再封装到x中(每次都是new)
     */
    public x D() {
        if (this.i == null) {
            return null;
        } else {
            Bundle b = this.i.GetMapStatus();
            x mapStatus = new x();
            mapStatus.a(b);
            return mapStatus;
        }
    }
}
package com.baidu.mapapi.map;
public class BaiduMap {
    private d j;
    /**
     * 地图状态的源数据 x -> MapStatus 
     * 将状态封装到Bundle中,再封装到x中,再封装到MapStatus中(每次都是new)
     */
    public final MapStatus getMapStatus() {
        if (this.j == null) {
            return null;
        } else {
            x inner = this.j.D();// 获取地图状态的源数据
            return MapStatus.a(inner);
        }
    }
}
  • 因此要重新修改下地图的缩放等级:
		// 设置缩放等级 baiduMap.j.a(max, min);
        // baiduMap.setMaxAndMinZoomLevel(33,8);
        try {
            Class<?> mapClass = baiduMap.getClass();
            Field jField = mapClass.getDeclaredField("j");
            jField.setAccessible(true);
            d dObject = (d) jField.get(baiduMap);
            dObject.a(33.0f, 8.0f);
            Log.e("999", "当前级数1 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数1 出错==" + e.getMessage());
        }
		// 设置地图类型 
		baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
		// 再次设置缩放等级 baiduMap.j.T();
		try {
            Class<?> dClass = baiduMap.getClass();
            Field nameField = dClass.getDeclaredField("j");
            nameField.setAccessible(true);
            d dObject = (d) nameField.get(baiduMap);

            Class<?> cClass = dObject.getClass();
            Field maxField = cClass.getDeclaredField("a");
            maxField.setAccessible(true);
            maxField.set(dObject, 33.0f);

            Field mapControllerField = cClass.getDeclaredField("P");
            mapControllerField.setAccessible(true);
            MapController mapController = (MapController) mapControllerField.get(dObject);
            mapController.mMaxZoomLevel = 33.0f;

            Log.e("999", "当前级数2 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数2 出错==" + e.getMessage());
        }
  • 第二次测试效果:
2022-12-17 15:42:15.381 12254/com.xxx.debug E/999: 当前级数1 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:42:15.399 12254/com.xxx.debug E/999: 当前级数2 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:42:15.893 12254/com.xxx.debug E/999: onMapStatusChangeFinish=8.0,cur=8.0,max=33.0,min=8.0
2022-12-17 15:43:19.349 12254/com.xxx.debug E/999: onMapStatusChangeFinish=13.777459,cur=13.777459,max=33.0,min=8.0 // 放大
2022-12-17 15:43:20.978 12254/com.xxx.debug E/999: onMapStatusChangeFinish=16.235798,cur=16.235798,max=33.0,min=8.0 // 放大
2022-12-17 15:43:22.579 12254/com.xxx.debug E/999: onMapStatusChangeFinish=20.0,cur=20.0,max=33.0,min=8.0 // 放大
2022-12-17 15:43:22.609 12254/com.xxx.debug E/999: onMapStatusChangeFinish=20.0,cur=20.0,max=33.0,min=8.0 // 放大
2022-12-17 15:46:00.808 12254/com.xxx.debug E/999: onMapStatusChangeFinish=4.0,cur=4.0,max=33.0,min=8.0 // 缩小
2022-12-17 15:46:00.824 12254/com.xxx.debug E/999: onMapStatusChangeFinish=4.0,cur=4.0,max=33.0,min=8.0 // 缩小

>>>>发现最大放大级数始终为33,但是一直放大,也只能放大到20级,而且缩小也是可以缩小到4.0 而不是 8.0,说明这个设置最大最小缩放级数 是无效的

  • 要不缩放等级多设置一次(万一和nativeSetMaxAndMinZoomLevel有关系):
		// 设置缩放等级 baiduMap.j.a(max, min);
        // baiduMap.setMaxAndMinZoomLevel(33,8);
        try {
            Class<?> mapClass = baiduMap.getClass();
            Field jField = mapClass.getDeclaredField("j");
            jField.setAccessible(true);
            d dObject = (d) jField.get(baiduMap);
            dObject.a(33.0f, 8.0f);
            Log.e("999", "当前级数1 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数1 出错==" + e.getMessage());
        }
		// 设置地图类型 
		baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
		// 再次设置缩放等级 baiduMap.j.T();
		try {
            Class<?> dClass = baiduMap.getClass();
            Field nameField = dClass.getDeclaredField("j");
            nameField.setAccessible(true);
            d dObject = (d) nameField.get(baiduMap);

            Class<?> cClass = dObject.getClass();
            Field maxField = cClass.getDeclaredField("a");
            maxField.setAccessible(true);
            maxField.set(dObject, 33.0f);

            Field mapControllerField = cClass.getDeclaredField("P");
            mapControllerField.setAccessible(true);
            MapController mapController = (MapController) mapControllerField.get(dObject);
            mapController.mMaxZoomLevel = 33.0f;

            Log.e("999", "当前级数2 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数2 出错==" + e.getMessage());
        }
		// 设置缩放等级 baiduMap.j.a(max, min);
        try {
            Class<?> mapClass = baiduMap.getClass();
            Field jField = mapClass.getDeclaredField("j");
            jField.setAccessible(true);
            d dObject = (d) jField.get(baiduMap);
            dObject.a(33.0f, 8.0f);
            Log.e("999", "当前级数3 cur==" + baiduMap.getMapStatus().zoom + ",最大级数 max==" + baiduMap.getMaxZoomLevel() + ",最小级数 min ==" + baiduMap.getMinZoomLevel());
        } catch (Exception e) {
            Log.e("999", "修改级数3 出错==" + e.getMessage());
        }
  • 第三次测试效果:
2022-12-17 15:42:15.381 12254/com.xxx.debug E/999: 当前级数1 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:42:15.399 12254/com.xxx.debug E/999: 当前级数2 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:42:15.893 12254/com.xxx.debug E/999: onMapStatusChangeFinish=8.0,cur=8.0,max=33.0,min=8.0
2022-12-17 15:43:19.349 12254/com.xxx.debug E/999: onMapStatusChangeFinish=13.777459,cur=13.777459,max=33.0,min=8.0 // 放大
2022-12-17 15:43:20.978 12254/com.xxx.debug E/999: onMapStatusChangeFinish=16.235798,cur=16.235798,max=33.0,min=8.0 // 放大
2022-12-17 15:43:22.579 12254/com.xxx.debug E/999: onMapStatusChangeFinish=20.0,cur=20.0,max=33.0,min=8.0 // 放大
2022-12-17 15:43:22.609 12254/com.xxx.debug E/999: onMapStatusChangeFinish=20.0,cur=20.0,max=33.0,min=8.0 // 放大
2022-12-17 15:46:00.808 12254/com.xxx.debug E/999: onMapStatusChangeFinish=4.0,cur=4.0,max=33.0,min=8.0 // 缩小
2022-12-17 15:46:00.824 12254/com.xxx.debug E/999: onMapStatusChangeFinish=4.0,cur=4.0,max=33.0,min=8.0 // 缩小



2022-12-17 15:53:20.731 13109/com.xxx.debug E/999: 当前级数1 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:53:20.738 13109/com.xxx.debug E/999: 当前级数2 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:53:20.740 13109/com.xxx.debug E/999: 当前级数3 cur==12.0,最大级数 max==33.0,最小级数 min ==8.0
2022-12-17 15:53:21.269 13109/com.xxx.debug E/999: onMapStatusChangeFinish=8.0,cur=8.0,max=33.0,min=8.0 // 放大
2022-12-17 15:53:29.871 13109/com.xxx.debug E/999: onMapStatusChangeFinish=11.021665,cur=11.021665,max=33.0,min=8.0 // 放大
2022-12-17 15:53:30.886 13109/com.xxx.debug E/999: onMapStatusChangeFinish=13.607431,cur=13.607431,max=33.0,min=8.0 // 放大
2022-12-17 15:53:33.068 13109/com.xxx.debug E/999:onMapStatusChangeFinish=21.0,cur=21.0,max=33.0,min=8.0 // 放大
2022-12-17 15:55:34.871 13109/com.xxx.debug E/999:onMapStatusChangeFinish=8.0,cur=8.0,max=33.0,min=8.0 // 缩小

>>>>地图竟然可以放大到了21级5米,比正常多了有一个级数

  • 等级虽然放大到21级,但是看不到卫星图,只剩下 标注、高铁和地铁等信息(不显示 高速路、桥、隧道、省道):

在这里插入图片描述

在这里插入图片描述

█ 看下设置地图类型的过程(可忽略)

  baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);// 设置地图类型 2,表示 卫星图
public class BaiduMap {
    private d j;// 地图状态、缩放等级等(因为混淆,所以不同版本的aar文件,打开不一定都是 d.class)
    /**
     * 设置地图类型
     */
    public final void setMapType(int type) {
        if (this.j != null) {
            Map<String, Object> map = new HashMap();
            map.put("T", type);
            com.baidu.platform.comapi.a.h.a().a("B", "M", "4", map);
            switch(type) {// type = 2
            case 1:
                。。。。。。
                break;
            case 2:
                this.j.a(true);// 执行这个 ShowSatelliteMap
                this.j.B(this.T);
                this.j.C(this.U);// ShowLayers
                this.j.j(true);
                break;
            case 3:
                。。。。。。
            }
            if (OpenLogUtil.isMapLogEnable()) {
                com.baidu.mapsdkplatform.comapi.commonutils.b.a().a("BasicMap setMapType type = " + type);
            }
        }
    }
}
public class d implements com.baidu.mapsdkplatform.comjni.a.a.a {
    public void a(boolean on) {
        if (this.i != null) {
            this.n = on;// 是否显示卫星地图
            this.T();// 执行这个
            this.i.ShowSatelliteMap(this.n);
            if (this.P != null) {
                if (on) {
                    this.P.setMapTheme(2, new Bundle());
                } else {
                    this.P.setMapTheme(1, new Bundle());
                }
            }
        }
    }
}
public class d implements com.baidu.mapsdkplatform.comjni.a.a.a {
    /**
     * 检查缩放级数
     */
    private void T() {
        if (!this.q && !this.n && !this.m && !this.r) {// q=false,n=true(是否显示卫星地图),m=false,r=false
            this.a = this.c;
            if (this.P != null) {
                this.P.mMaxZoomLevel = this.a;
            }
        } else {
            if (this.a > 20.0F) {// a=33.0,b=8.0,c=33.0
                this.a = 20.0F;
                if (this.P != null) {// P.mMaxZoomLevel=33.0,P.mMinZoomLevel=8.0
                    this.P.mMaxZoomLevel = 20.0F;
                }
            }

            if (this.D().a > 20.0F) {// this.D().a = 12.0
                x mapStatusInner = this.D();// 地图状态的源数据
                mapStatusInner.a = 20.0F;
                this.a(mapStatusInner);
            }
        }
    }
}

█ 关于坐标转换

  • 坐标系

    WGS84坐标系(世界大地坐标系统)GPS坐标系,由美国国防部制图局建立,是目前广泛使用的GPS全球卫星定位系统使用的坐标系
    CGCS2000坐标系(国家大地坐标 )GPS坐标系,自2008年7月1日起,中国全面启用2000国家大地坐标系
    GCJ-02(又叫火星坐标系)国测局02年发布的坐标,经过特殊算法将实际的坐标加密成新的坐标,通常国内多家地图厂商都用这个。
    BD09坐标百度坐标系。在GCJ-02坐标系基础上再次加密
  • 不同地图使用的坐标系

地图坐标系说明
手机GPSWGS-84坐标系安卓和ios原生方法获取到的是WGS84坐标系的坐标
天地图CGCS-2000坐标系中国当前最新的国家大地坐标系,与WGS84坐标系都是地心坐标系,相差不大。
高德-境内GCJ-02坐标系在WGS84坐标系上进行了一次加密得到的坐标系
google地图-境内GCJ-02坐标系数据来源于高德
google地图-境外WGS-84坐标系GPS坐标系
百度-境内BD-09坐标系在GCJ-02上再进行了一次加密得到的
百度-境外WGS-84坐标系GPS坐标系
腾讯地图(soso)-境内GCJ-02坐标系在WGS84坐标系上进行了一次加密得到的坐标系
微软bing地图(BingMap)WGS-84坐标系GPS坐标系
搜狗地图-境内搜狗坐标系在GCJ-02上再进行了一次加密得到的
图吧地图(MapBar)-境内图吧坐标系在GCJ-02上再进行了一次加密得到的
阿里云地图-境内GCJ-02坐标系在WGS84坐标系上进行了一次加密得到的坐标系
灵图地图(51ditu)-境内GCJ-02坐标系在WGS84坐标系上进行了一次加密得到的坐标系
  • 百度坐标和火星坐标的转换1:CoordinateConverter
//初始化左边转换工具类,指定源坐标类型和坐标数据
//sourceLatLng 待转换坐标
CoordinateConverter converter  = new CoordinateConverter()
        .from(COMMON)
        .coord(sourceLatLng);

//转换坐标
LatLng desLatLng = converter.convert();

  • 百度坐标和火星坐标的转换2:CoordTrans
public class CoordTrans {
    public CoordTrans() {
    }

    public static LatLng baiduToGcj(LatLng latLng) {
        if (null == latLng) {
            return null;
        } else {
            double[] gcjLatLng = JNITools.baiduToGcj(latLng.latitude, latLng.longitude);
            return null == gcjLatLng ? null : new LatLng(gcjLatLng[0], gcjLatLng[1]);
        }
    }

    public static LatLng gcjToBaidu(LatLng latLng) {
        if (null == latLng) {
            return null;
        } else {
            double[] bdLatLng = JNITools.gcjToBaidu(latLng.latitude, latLng.longitude);
            return null == bdLatLng ? null : new LatLng(bdLatLng[0], bdLatLng[1]);
        }
    }

    public static LatLng wgsToBaidu(LatLng latLng) {
        if (null == latLng) {
            return null;
        } else {
            double[] bdLatLng = JNITools.wgsToBaidu(latLng.latitude, latLng.longitude);
            return null == bdLatLng ? null : new LatLng(bdLatLng[0], bdLatLng[1]);
        }
    }
}

█ 相关资料

提示:这里是参考的相关文章

  1. 2015-11-27 百度地图API二:根据标注点坐标范围计算显示缩放级别zoom自适应显示地图_liusaint1992的博客-CSDN博客_百度地图不同zoom对应的范围
  2. 没答案2015-12-21 百度地图提供的安卓API怎样提高最大放大级别?-移动开发-CSDN问答
  3. js版本2020-07-16 百度地图突破19级缩放限制解决方案_lihefei_coder的博客-CSDN博客
  4. 最新版本支持2021.08.31 百度地图web端SDK最大只能缩放到20米问题-百度开发者中心
  5. 2D版本19级10米。BMapGL 3D版本21级5米2022年5月13日 地图升级一下 — 希望缩放级别能提高点 - 点击领取
  6. 2022-09-03 国内常用地图坐标系_任玉的博客-CSDN博客_地图坐标系
  7. 2022-08-05 《学习总结》天地图_快学点111的博客-CSDN博客_天地图用的是什么坐标系

█ 免责声明

博主分享的所有文章内容,部分参考网上教程,引用大神高论,部分亲身实践,记下笔录,内容可能存在诸多不实之处,还望海涵,本内容仅供学习研究使用,切勿用于商业用途,若您是部分内容的作者,不喜欢此内容被分享出来,可联系博主说明相关情况通知删除,感谢您的理解与支持!

转载请注明出处:
https://blog.csdn.net/ljb568838953/article/details/128350559

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值