1.效果图:
2.运行结果:
E/TAG: 最初始的高德选点坐标: 113.402847,23.164699
E/TAG: g84坐标点: 113.39732255710973,23.167184411566584
E/TAG: g02的坐标点: 113.40284721155093,23.16469943818697
E/TAG: 最终的坐标点: 113.40284698937967,23.164707045643137
3.说明:
最近碰到一个硬件,经纬度是gps获取的 ,在Android设备上,用高德地图显示的时候,出现了坐标偏移,此demo正是为了解决此事而来
4.添加高德地图引用:
//3d地图 和导航
implementation 'com.amap.api:navi-3dmap:latest.integration'
//定位
implementation 'com.amap.api:location:latest.integration'
//搜索
implementation 'com.amap.api:search:latest.integration'
5.主界面:
package com.example.admin.zkotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import com.amap.api.maps.CoordinateConverter
import com.amap.api.maps.model.LatLng
import com.kaisavx.AircraftController.util.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
//经过测试 本例子中, 其实高德坐标 就是 火星坐标gcj02 误差非常小
internal var lat = 23.164699 //大洋图文
internal var lon = 113.402847
private var oldposition: LatLng? = null //最初始的高德选点坐标
private var g84position: LatLng? = null //最初始的高德选点坐标 转换成g84
private var g02position: LatLng? = null // g84 转g02
private var endposition: LatLng? = null // g02 转 高德
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
oldposition = LatLng(lat, lon)
tv_old_gaode!!.text = oldposition.toString()
Log.e("TAG", "最初始的高德选点坐标: " + oldposition!!.longitude + "," + oldposition!!.latitude)
g84position = gcj02towgs84(LatLng(oldposition!!.latitude, oldposition!!.longitude))
tv_gps!!.text = g84position.toString()
Log.e("TAG", "g84坐标点: " + g84position!!.longitude + "," + g84position!!.latitude)
g02position = wgs84togcj02(g84position!!)
tv_j02!!.text = g02position.toString()
Log.e("TAG", "g02的坐标点: " + g02position!!.longitude + "," + g02position!!.latitude)
btn_coord!!.setOnClickListener {
endposition = convert(g84position!!, CoordinateConverter.CoordType.GPS) //设置需要转换的坐标点和坐标类型
Log.e("TAG", "最终的坐标点: " + endposition!!.longitude + "," + endposition!!.latitude)
tv_gaode!!.text = endposition.toString()
}
}
/**
* 根据类型 转换 坐标
*/
private fun convert(sourceLatLng: LatLng, coord: CoordinateConverter.CoordType): LatLng {
val converter = CoordinateConverter(this)
// CoordType.GPS 待转换坐标类型
converter.from(coord)
// sourceLatLng待转换坐标点
converter.coord(sourceLatLng)
// 执行转换操作
return converter.convert()
}
}
6.主界面UI:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="高德选点的坐标:" />
<TextView
android:id="@+id/tv_old_gaode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0.0" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="GPS-WGS84坐标:" />
<TextView
android:id="@+id/tv_gps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0.0" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="火星坐标:" />
<TextView
android:id="@+id/tv_j02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0.0" />
<Button
android:id="@+id/btn_coord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始转换" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="高德SDK转换后的坐标:" />
<TextView
android:id="@+id/tv_gaode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0.0:" />
</LinearLayout>
7.转换算法 MapUtils.kt,注意:经过这个算法算出来的坐标,还是会存在误差的,但是对于我们的商业应用来说,差不多够用了
package com.kaisavx.AircraftController.util
import android.graphics.Bitmap
import android.os.Environment
import android.util.Log
import com.amap.api.maps.AMap
import com.amap.api.maps.model.LatLng
import com.amap.api.services.core.LatLonPoint
import com.amap.api.services.geocoder.GeocodeResult
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.geocoder.RegeocodeResult
import java.io.File
import java.io.FileOutputStream
/**
* Created by windless on 2017/10/12.
*/
fun getLocationsCenter(locations: List<LatLng>): LatLng {
if (locations.size == 1) {
return locations.first()
}
var x = 0.0
var y = 0.0
var z = 0.0
locations.forEach {
val latitude = it.latitude * Math.PI / 180
val longitude = it.longitude * Math.PI / 180
x += Math.cos(latitude) * Math.cos(longitude)
y += Math.cos(latitude) * Math.sin(longitude)
z += Math.sin(latitude)
}
x /= locations.size
y /= locations.size
z /= locations.size
val centerLongitude = Math.atan2(y, x)
val centerSquareRoot = Math.sqrt(x * x + y * y)
val centerLatitude = Math.atan2(z, centerSquareRoot)
return LatLng(centerLatitude * 180 / Math.PI, centerLongitude * 180 / Math.PI)
}
fun getMapScreenShootFile(fileName: String): File {
val dir = Environment.getExternalStorageDirectory()
val mapScreenShootDir = File(File(dir, "jellyfish"), "maps")
return File(mapScreenShootDir, fileName)
}
fun saveMapScreenShoot(map: AMap, fileName: String) {
val dir = Environment.getExternalStorageDirectory()
val mapScreenShootDir = File(File(dir, "jellyfish"), "maps")
if (!mapScreenShootDir.exists()) {
mapScreenShootDir.mkdirs()
}
val filePath = File(mapScreenShootDir, fileName)
map.getMapScreenShot(object : AMap.OnMapScreenShotListener {
override fun onMapScreenShot(bitmap: Bitmap?) {
if (bitmap == null) {
return
}
if (filePath.exists()) {
filePath.delete()
}
val fos = FileOutputStream(filePath)
val ok = bitmap.compress(Bitmap.CompressFormat.PNG, 50, fos)
if (ok) {
try {
fos.flush()
} catch (e: Exception) {
Log.d("MapUtils", "save map screen shoot failed", e)
}
try {
fos.close()
} catch (ignored: Exception) {
}
}
}
override fun onMapScreenShot(bitmap: Bitmap?, status: Int) {
Log.d("MapUtils", "$status")
}
})
}
val x_PI = 3.14159265358979324 * 3000.0 / 180.0
val PI = 3.1415926535897932384626
val a = 6378245.0
val ee = 0.00669342162296594323
fun wgs84togcj02(latlng: LatLng): LatLng {
val lat = latlng.latitude
val lng = latlng.longitude
if (outOfChina(lng, lat)) {
return latlng
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0)
var dlng = transformlng(lng - 105.0, lat - 35.0)
val radlat = lat / 180.0 * PI
var magic = Math.sin(radlat)
magic = 1 - ee * magic * magic
val sqrtmagic = Math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
val mglat = lat + dlat
val mglng = lng + dlng
return LatLng(mglat, mglng)
}
}
fun gcj02towgs84(latlng: LatLng): LatLng {
val lat = latlng.latitude
val lng = latlng.longitude
if (outOfChina(lng, lat)) {
return latlng
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0)
var dlng = transformlng(lng - 105.0, lat - 35.0)
val radlat = lat / 180.0 * PI
var magic = Math.sin(radlat)
magic = 1 - ee * magic * magic
val sqrtmagic = Math.sqrt(magic)
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI)
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI)
val mglat = lat + dlat
val mglng = lng + dlng
return LatLng(
lat * 2 - mglat,
lng * 2 - mglng
)
}
}
private fun outOfChina(lng: Double, lat: Double): Boolean {
return (lng < 72.004 || lng > 137.8347) && (lat < 0.8293 || lat > 55.8271)
}
private fun transformlat(lng: Double, lat: Double): Double {
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat
+ 0.2 * Math.sqrt(Math.abs(lng))
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0
return ret
}
private fun transformlng(lng: Double, lat: Double): Double {
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat
+ 0.1 * Math.sqrt(Math.abs(lng))
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0
return ret
}
end
来源:CSDN
作者:cf8833
链接:https://blog.csdn.net/cf8833/article/details/103770590