• 安卓定位及坐标转换


    博客: 安卓之家
    微博: 追风917
    CSDN: 蒋朋的家
    简书: 追风917

    每日一景

    定位


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

    • 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();
         }
        }
    

    代码放到了这个 Gist: https://gist.github.com/jp1017/dc87d742ae5d1edf9fad0b43223f74bb

    说明一点: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;
    	}
    

    好了,就是这样子了,部分细节请来 gayhub:

    coordtransform

    最后,非常感谢您的阅读,有任何疑问,可以后面评论,谢谢!

    神奇的安卓开发网站:http://androidcat.com/

    安卓开源库收集整理:https://github.com/XXApple/AndroidLibs

    分享是一种美德,更是一种生活方式!!

    也许你会说我是一个梦想者,但我不是唯一的一个。

    悦分享,越快乐_

    欢迎交流,转载请注明出处,谢谢!

  • 相关阅读:
    QT槽和信号机制介绍
    J2EE面试题之二
    .net 面试题系列文章一(附答案)
    SUN JAVA面试笔试题
    用友在清华的笔试题
    Java面试笔试题整理
    雅虎公司C#笔试题(之一)
    Oracle面试题及答案整理
    一些著名的大公司JAVA面试题目
    百度技术研发笔试题目1
  • 原文地址:https://www.cnblogs.com/jp1017/p/5668265.html
Copyright © 2020-2023  润新知