文档章节

Android定位及bd09,gcj02,wgs84坐标转换,适用百度、高德地图

沐风storm
 沐风storm
发布于 2016/09/27 08:57
字数 1373
阅读 502
收藏 0

定位

需要添加位置权限,这里有两个:

  • android.permission.ACCESS_COARSE_LOCATION – 允许 API 利用 WiFi 或移动蜂窝数据(或同时利用两者)来确定设备位置。API 返回的位置精确度大约相当于城市街区。
  • android.permission.ACCESS_FINE_LOCATION – 允许 API 利用包括全球定位系统 (GPS) 在内的可用位置提供商以及 WiFi 和移动蜂窝数据尽可能精确地确定位置。

1 安卓 SDK android.location.LocationManager

单独获取位置信息还是很简单的:

 LocationManager mManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    Location mLocation = mManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);//需要权限检测,上面添加

    double mLat = location.getLatitude();//获取纬度
    double mLng = location.getLongitude();//获取经度

 

实际开发中,我们需要实时定位,就需要监听位置变化来实现,

声明 LocationListener,然后调用 requestLocationUpdates 方法即可:

   /**
     * 获取原生gps信息,代码放 MainActivity 里就可以
     */
    public void getGPSInfo() {
        LocationManager mManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Location mLocation = mManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        updateGPSInfo(mLocation);

        mManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 8, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                updateGPSInfo(mLocation);//位置变化时,更新位置信息
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            @Override
            public void onProviderEnabled(String provider) {
                // 当GPS LocationProvider可用时,更新位置
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED
                        && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                        != PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                updateGPSInfo(mManager.getLastKnownLocation(provider));
            }

            @Override
            public void onProviderDisabled(String provider) {

            }
        });
    }


    /**
     * 更新经纬度信息
     * @param location
     */
    public void updateGPSInfo(Location location) {
      if (location != null) {
           mLat = location.getLatitude();
           mLng = location.getLongitude();
     }
    }

 

说明一点:requestLocationUpdates 方法有多个重载方法:

常用的是下面这个:

public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)

当时间超过 minTime(单位:毫秒),或者位置移动超过 minDistance(单位:米),就会调用 listener 中的方法更新 GPS 信息。
如果要尽可能实时的更新 GPS 信息,请将 minTime 和 minDistance 都设置成0。

官方文档:https://developer.android.com/reference/android/location/LocationManager.html

2 google 地图 api

参考这里,很详细了:https://developers.google.com/maps/documentation/android-api/location?hl=zh-cn#_2

3 高德地图 api

参考高德地图 定位api :http://lbs.amap.com/api/android-location-sdk/locationsummary/

4 百度地图 api

参考百度地图api:http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/getloc

坐标转换

安卓系统常用的 GPS 坐标有下面几种:

名称 别名 标准 获取方式 应用场合
wgs84 地球坐标 国际标准 从 GPS 设备中获取的坐标数据 国际地图提供商,谷歌国际地图
gcj02 火星坐标,国测局坐标 中国标准 从国行移动设备中定位获取的坐标数据 高德地图,谷歌地图,腾讯地图,阿里云地图
bd09 百度坐标 百度标准 百度在火星坐标上二次加密后的坐标数据 百度地图

1 gcj02 转成 bd09

可以使用百度地图 SDK 里的工具类 CoordinateConverter

    /**
     * gcj02 坐标转换成百度坐标
     *
     * @param srLatLng 要转换的 gcj02 经纬度
     * @return 转换后的百度经纬度
     */
    public LatLng convertGPSToBaidu(LatLng srLatLng) {
        CoordinateConverter converter = new CoordinateConverter();
        converter.from(CoordinateConverter.CoordType.COMMON);
        converter.coord(srLatLng);
        return converter.convert();
    }

另外一个是刚从 gayhub 上找到的:

    /**
     * 火星坐标系(GCJ-02)转百度坐标系(BD-09)
     * 
     * 谷歌、高德——>百度
     * @param lng 火星坐标经度
     * @param lat 火星坐标纬度
     * @return 百度坐标数组
     */
    public static double[] gcj02tobd09(double lng, double lat) {
        double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_pi);
        double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_pi);
        double bd_lng = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        return new double[] { bd_lng, bd_lat };
    }

2 bd09 转成 gcj02

万能的 gayhub 拯救了我们:

    /**
     * 百度坐标系(BD-09)转火星坐标系(GCJ-02)
     * 
     * 百度——>谷歌、高德
     * @param bd_lon 百度坐标纬度
     * @param bd_lat 百度坐标经度
     * @return 火星坐标数组
     */
    public static double[] bd09togcj02(double bd_lon, double bd_lat) {
        double x = bd_lon - 0.0065;
        double y = bd_lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double gg_lng = z * Math.cos(theta);
        double gg_lat = z * Math.sin(theta);
        return new double[] { gg_lng, gg_lat };
    }

另外,高德地图也提供了 api :如何将非高德坐标转换为高德坐标系

3 wgs84 转成 gcj02

    /**
     * WGS84转GCJ02(火星坐标系)
     * 
     * @param lng WGS84坐标系的经度
     * @param lat WGS84坐标系的纬度
     * @return 火星坐标数组
     */
    public static double[] wgs84togcj02(double lng, double lat) {
        if (out_of_china(lng, lat)) {
            return new double[] { lng, lat };
        }
        double dlat = transformlat(lng - 105.0, lat - 35.0);
        double dlng = transformlng(lng - 105.0, lat - 35.0);
        double radlat = lat / 180.0 * pi;
        double magic = Math.sin(radlat);
        magic = 1 - ee * magic * magic;
        double sqrtmagic = Math.sqrt(magic);
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
        dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
        double mglat = lat + dlat;
        double mglng = lng + dlng;
        return new double[] { mglng, mglat };
    }

当然,这个也可以利用上面的高德的 api

4 gcj02 转成 wgs84

    /**
     * GCJ02(火星坐标系)转GPS84
     * 
     * @param lng 火星坐标系的经度
     * @param lat 火星坐标系纬度
     * @return WGS84坐标数组
     */
    public static double[] gcj02towgs84(double lng, double lat) {
        if (out_of_china(lng, lat)) {
            return new double[] { lng, lat };
        }
        double dlat = transformlat(lng - 105.0, lat - 35.0);
        double dlng = transformlng(lng - 105.0, lat - 35.0);
        double radlat = lat / 180.0 * pi;
        double magic = Math.sin(radlat);
        magic = 1 - ee * magic * magic;
        double sqrtmagic = Math.sqrt(magic);
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi);
        dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * pi);
        double mglat = lat + dlat;
        double mglng = lng + dlng;
        return new double[] { lng * 2 - mglng, lat * 2 - mglat };
    }

5 wgs84 转成 bd09

这个没有直接转的,需要 gcj02 做媒介

    /**
     * WGS坐标转百度坐标系(BD-09)
     * 
     * @param lng WGS84坐标系的经度
     * @param lat WGS84坐标系的纬度
     * @return 百度坐标数组
     */
    public static double[] wgs84tobd09(double lng, double lat) {
        double[] gcj = wgs84togcj02(lng, lat);
        double[] bd09 = gcj02tobd09(gcj[0], gcj[1]);
        return bd09;
    }

6 bd09 转成 wgs84

同上,需要媒介 gcj02

    /**
     * 百度坐标系(BD-09)转WGS坐标
     * 
     * @param lng 百度坐标纬度
     * @param lat 百度坐标经度
     * @return WGS84坐标数组
     */
    public static double[] bd09towgs84(double lng, double lat) {
        double[] gcj = bd09togcj02(lng, lat);
        double[] wgs84 = gcj02towgs84(gcj[0], gcj[1]);
        return wgs84;
    }

好了,就是这样子了

本文转载自:http://www.jianshu.com/p/ddc6141bac95

沐风storm
粉丝 0
博文 10
码字总数 4795
作品 0
武汉
程序员
私信 提问
GPS位置地图坐标系:WGS-84(GPS)、GCJ-02(Google地图)、BD-09(百度地图),OpenGIS

国家规定,中国大陆所有公开地理数据都需要至少用GCJ-02进行加密,也就是说我们从国内公司的产品中得到的数据,一定是经过了加密的。绝大部分国内互联网地图提供商都是使用GCJ-02坐标系,包括...

desaco
01/29
0
0
瓦片地图原理

引言 谷歌地图、百度地图、高德地图、腾讯地图、Bing地图这些互联网地图是怎么制作的? 经纬度 地球是一个椭球,Datum是一组用于描述这个椭球的数据集合。最常用的一个Datum是WGS84(World G...

丹追兵
2017/09/20
0
0
iOS 高德地图百度地图实现后台定位

坐标体系 WGS84: 大地坐标系,广泛使用的 GPS 定位系统采用的坐标系. GCJ02: 火星坐标系,由中国测绘局对 WGS84进行加密后得到的坐标系. BD09: 百度坐标,针对火星坐标再次加密所得BD09II 位百度...

maker997
2018/01/06
0
0
浅谈百度Baidu坐标系反转至WGS84的三种思路

摘要:基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图是基于BD09坐标系的,GPS坐标(WGS84)或者其他常见的标准坐标是无法准确在地图上进行展示的,但是互联网在线情况下,...

sinat_34719507
2017/03/09
0
0
简谈百度坐标反转至WGS84的三种思路

文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 基于百度地图进行数据展示是目前项目中常见场景,但是因为百度地图是基于BD09坐标...

李晓晖
2017/01/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Giraph源码分析(八)—— 统计每个SuperStep中参与计算的顶点数目

作者|白松 目的:科研中,需要分析在每次迭代过程中参与计算的顶点数目,来进一步优化系统。比如,在SSSP的compute()方法最后一行,都会把当前顶点voteToHalt,即变为InActive状态。所以每次...

数澜科技
今天
4
0
Xss过滤器(Java)

问题 最近旧的系统,遇到Xss安全问题。这个系统采用用的是spring mvc的maven工程。 解决 maven依赖配置 <properties><easapi.version>2.2.0.0</easapi.version></properties><dependenci......

亚林瓜子
今天
10
0
Navicat 快捷键

操作 结果 ctrl+q 打开查询窗口 ctrl+/ 注释sql语句 ctrl+shift +/ 解除注释 ctrl+r 运行查询窗口的sql语句 ctrl+shift+r 只运行选中的sql语句 F6 打开一个mysql命令行窗口 ctrl+l 删除一行 ...

低至一折起
今天
9
0
Set 和 Map

Set 1:基本概念 类数组对象, 内部元素唯一 let set = new Set([1, 2, 3, 2, 1]); console.log(set); // Set(3){ 1, 2, 3 } [...set]; // [1, 2, 3] 接收数组或迭代器对象 ...

凌兮洛
今天
4
0
PyTorch入门笔记一

张量 引入pytorch,生成一个随机的5x3张量 >>> from __future__ import print_function>>> import torch>>> x = torch.rand(5, 3)>>> print(x)tensor([[0.5555, 0.7301, 0.5655],......

仪山湖
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部