多种类型经纬度转换工具类

This commit is contained in:
lijia 2024-12-13 18:04:33 +08:00
parent 82b1413429
commit 01bd0e03ff
2 changed files with 572 additions and 0 deletions

View File

@ -0,0 +1,33 @@
package com.dahe.mylibrary.utils;
/**
* @ClassName Gps
* @Author john
* @Date 2024/12/13 17:25
* @Description TODO
*/
public class Gps {
private double wgLon;
private double wgLat;
public Gps(double wgLat,double wgLon) {
this.wgLat = wgLat;
this.wgLon = wgLon;
}
public double getWgLon() {
return wgLon;
}
public void setWgLon(double wgLon) {
this.wgLon = wgLon;
}
public double getWgLat() {
return wgLat;
}
public void setWgLat(double wgLat) {
this.wgLat = wgLat;
}
}

View File

@ -0,0 +1,539 @@
package com.dahe.mylibrary.utils;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;
/**
* @author ondear
* time : 16/11/13
* desc : 定位相关工具类
*/
public class RxLocationUtils {
public static double pi = 3.1415926535897932384626;
public static double a = 6378245.0;
public static double ee = 0.00669342162296594323;
private static OnLocationChangeListener mListener;
private static MyLocationListener myLocationListener;
private static LocationManager mLocationManager;
/**
* 判断Gps是否可用
*
* @return {@code true}: <br>{@code false}:
*/
public static boolean isGpsEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 判断定位是否可用
*
* @return {@code true}: <br>{@code false}:
*/
public static boolean isLocationEnabled(Context context) {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER) || lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 打开Gps设置界面
*/
public static void openGpsSettings(Context context) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 注册
* <p>使用完记得调用{@link #unregister()}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.INTERNET"/>}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>}</p>
* <p>需添加权限 {@code <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>}</p>
* <p>如果{@code minDistance}为0则通过{@code minTime}来定时更新</p>
* <p>{@code minDistance}不为0则以{@code minDistance}为准</p>
* <p>两者都为0则随时刷新</p>
*
* @param minTime 位置信息更新周期单位毫秒
* @param minDistance 位置变化最小距离当位置距离变化超过此值时将更新位置信息单位
* @param listener 位置刷新的回调接口
* @return {@code true}: 初始化成功<br>{@code false}: 初始化失败
*/
public static boolean register(Context context, long minTime, long minDistance, OnLocationChangeListener listener) {
if (listener == null) return false;
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
return false;
}
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
mListener = listener;
if (!isLocationEnabled(context)) {
ToastUtils.showToast(context, "无法定位,请打开定位服务");
return false;
}
String provider = mLocationManager.getBestProvider(getCriteria(), true);
Location location = mLocationManager.getLastKnownLocation(provider);
if (location != null) listener.getLastKnownLocation(location);
if (myLocationListener == null) myLocationListener = new MyLocationListener();
mLocationManager.requestLocationUpdates(provider, minTime, minDistance, myLocationListener);
return true;
}
/**
* 注销
*/
public static void unregister() {
if (mLocationManager != null) {
if (myLocationListener != null) {
mLocationManager.removeUpdates(myLocationListener);
myLocationListener = null;
}
mLocationManager = null;
}
}
/**
* 设置定位参数
*
* @return {@link Criteria}
*/
private static Criteria getCriteria() {
Criteria criteria = new Criteria();
//设置定位精确度 Criteria.ACCURACY_COARSE比较粗略Criteria.ACCURACY_FINE则比较精细
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//设置是否要求速度
criteria.setSpeedRequired(false);
// 设置是否允许运营商收费
criteria.setCostAllowed(false);
//设置是否需要方位信息
criteria.setBearingRequired(false);
//设置是否需要海拔信息
criteria.setAltitudeRequired(false);
// 设置对电源的需求
criteria.setPowerRequirement(Criteria.POWER_LOW);
return criteria;
}
/**
* 根据经纬度获取地理位置
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return {@link Address}
*/
public static Address getAddress(Context context, double latitude, double longitude) {
Geocoder geocoder = new Geocoder(context, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
if (addresses.size() > 0) return addresses.get(0);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 根据经纬度获取所在国家
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在国家
*/
public static String getCountryName(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getCountryName();
}
/**
* 根据经纬度获取所在地
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在地
*/
public static String getLocality(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getLocality();
}
/**
* 根据经纬度获取所在街道
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在街道
*/
public static String getStreet(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "unknown" : address.getAddressLine(0);
}
/**
* 根据经纬度获取详细地址
*
* @param context 上下文
* @param latitude 纬度
* @param longitude 经度
* @return 所在街道
*/
public static String getFeature(Context context, double latitude, double longitude) {
Address address = getAddress(context, latitude, longitude);
return address == null ? "未知地点" : address.getFeatureName();
}
//------------------------------------------坐标转换工具start--------------------------------------
/**
* GPS坐标 转换成 角度
* 例如 113.202222 转换成 113°128
*
* @param location
* @return
*/
public static String gpsToDegree(double location) {
double degree = Math.floor(location);
double minute_temp = (location - degree) * 60;
double minute = Math.floor(minute_temp);
// double second = Math.floor((minute_temp - minute)*60);
String second = new DecimalFormat("#.##").format((minute_temp - minute) * 60);
return (int) degree + "°" + (int) minute + "" + second + "";
}
/**
* 国际 GPS84 坐标系
* 转换成
* [国测局坐标系] 火星坐标系 (GCJ-02)
* <p>
* World Geodetic System ==> Mars Geodetic System
*
* @param lon 经度
* @param lat 纬度
* @return GPS实体类
*/
public static Gps GPS84ToGCJ02(double lat, double lon) {
if (outOfChina(lat, lon)) {
return null;
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 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);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLat, mgLon);
}
/**
* [国测局坐标系] 火星坐标系 (GCJ-02)
* 转换成
* 国际 GPS84 坐标系
*
* @param lon 火星经度
* @param lat 火星纬度
*/
public static Gps GCJ02ToGPS84(double lat, double lon) {
Gps gps = transform(lat, lon);
double lontitude = lon * 2 - gps.getWgLon();
double latitude = lat * 2 - gps.getWgLat();
return new Gps(latitude, lontitude);
}
/**
* 火星坐标系 (GCJ-02)
* 转换成
* 百度坐标系 (BD-09)
*
* @param gg_lon 经度
* @param gg_lat 纬度
*/
public static Gps GCJ02ToBD09(double gg_lat, double gg_lon) {
double x = gg_lon, y = gg_lat;
double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);
double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);
double bd_lon = z * Math.cos(theta) + 0.0065;
double bd_lat = z * Math.sin(theta) + 0.006;
return new Gps(bd_lat, bd_lon);
}
/**
* 国际 GPS84 坐标系
* 转换成
* 百度坐标系 (BD-09)
*
* @param lon 经度
* @param lat 纬度
*/
public static Gps GPS84ToBD09(double lat, double lon) {
Gps gps = GPS84ToGCJ02(lat,lon);
if (gps == null) {
return new Gps(lat,lon);
}
//GCJ-02 BD-09
return GCJ02ToBD09(gps.getWgLat(), gps.getWgLon());
}
/**
* 百度坐标系 (BD-09)
* 转换成
* 火星坐标系 (GCJ-02)
*
* @param bd_lon 百度*经度
* @param bd_lat 百度*纬度
* @return GPS实体类
*/
public static Gps BD09ToGCJ02(double bd_lat, double bd_lon) {
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);
double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);
double gg_lon = z * Math.cos(theta);
double gg_lat = z * Math.sin(theta);
return new Gps(gg_lat, gg_lon);
}
/**
* 百度坐标系 (BD-09)
* 转换成
* 国际 GPS84 坐标系
*
* @param bd_lon 百度*经度
* @param bd_lat 百度*纬度
* @return GPS实体类
*/
public static Gps BD09ToGPS84(double bd_lat, double bd_lon) {
Gps gcj02 = BD09ToGCJ02(bd_lat, bd_lon);
Gps map84 = GCJ02ToGPS84(gcj02.getWgLat(),
gcj02.getWgLon());
return map84;
}
/**
* 不在中国范围内
*
* @param lon 经度
* @param lat 纬度
* @return boolean值
*/
public static boolean outOfChina(double lat, double lon) {
if (lon < 72.004 || lon > 137.8347)
return true;
return lat < 0.8293 || lat > 55.8271;
}
/**
* 转化算法
*
* @param lon
* @param lat
* @return
*/
public static Gps transform(double lat, double lon) {
if (outOfChina(lat, lon)) {
return new Gps(lat, lon);
}
double dLat = transformLat(lon - 105.0, lat - 35.0);
double dLon = transformLon(lon - 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);
dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
double mgLat = lat + dLat;
double mgLon = lon + dLon;
return new Gps(mgLat, mgLon);
}
/**
* 纬度转化算法
*
* @param x
* @param y
* @return
*/
public static double transformLat(double x, double y) {
double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
+ 0.2 * Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
return ret;
}
/**
* 经度转化算法
*
* @param x
* @param y
* @return
*/
public static double transformLon(double x, double y) {
double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
* Math.sqrt(Math.abs(x));
ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
* pi)) * 2.0 / 3.0;
return ret;
}
public interface OnLocationChangeListener {
/**
* 获取最后一次保留的坐标
*
* @param location 坐标
*/
void getLastKnownLocation(Location location);
/**
* 当坐标改变时触发此函数如果Provider传进相同的坐标它就不会被触发
*
* @param location 坐标
*/
void onLocationChanged(Location location);
/**
* provider的在可用暂时不可用和无服务三个状态直接切换时触发此函数
*
* @param provider 提供者
* @param status 状态
* @param extras provider可选包
*/
void onStatusChanged(String provider, int status, Bundle extras);//位置状态发生改变
void onProviderEnabled(String provider);
void onProviderDisabled(String provider);
}
private static class MyLocationListener
implements LocationListener {
/**
* 当坐标改变时触发此函数如果Provider传进相同的坐标它就不会被触发
*
* @param location 坐标
*/
@Override
public void onLocationChanged(Location location) {
if (mListener != null) {
mListener.onLocationChanged(location);
}
}
/**
* provider的在可用暂时不可用和无服务三个状态直接切换时触发此函数
*
* @param provider 提供者
* @param status 状态
* @param extras provider可选包
*/
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
if (mListener != null) {
mListener.onStatusChanged(provider, status, extras);
}
switch (status) {
case LocationProvider.AVAILABLE:
Log.d("onStatusChanged", "当前GPS状态为可见状态");
break;
case LocationProvider.OUT_OF_SERVICE:
Log.d("onStatusChanged", "当前GPS状态为服务区外状态");
break;
case LocationProvider.TEMPORARILY_UNAVAILABLE:
Log.d("onStatusChanged", "当前GPS状态为暂停服务状态");
break;
}
}
/**
* provider被enable时触发此函数比如GPS被打开
*/
@Override
public void onProviderEnabled(String provider) {
if (mListener != null) {
mListener.onProviderEnabled(provider);
}
}
/**
* provider被disable时触发此函数比如GPS被关闭
*/
@Override
public void onProviderDisabled(String provider) {
if (mListener != null) {
mListener.onProviderDisabled(provider);
}
}
}
//===========================================坐标转换工具end====================================
private static final double EARTH_RADIUS = 6378137.0; //地球半径
/**
* 计算两个经纬度之间的距离
*
* @param longitude
* @param latitude
* @param longitude2
* @param latitude2
* @return 单位米
*/
public static double getDistance(double longitude, double latitude, double longitude2, double latitude2) {
double lat1 = rad(latitude);
double lat2 = rad(latitude2);
double a = lat1 - lat2;
double b = rad(longitude) - rad(longitude2);
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = Math.round(s * 10000) / 10000; //四舍五入
return s;
}
/**
* 弧度换为角度
* @param d
* @return
*/
private static double rad(double d) {
return d * Math.PI / 180.0;
}
}