我如何从 android studio 中的坐标获取地址
How can i get address from coordinates in android studio
我对反向地理编码有疑问。当我想将我的坐标转换为地址时,Geocoder returns 这个错误:
Caused by: java.io.IOException: grpc failed
这是我的代码:
val btnbymap = mycustomview.findViewById<Button>(R.id.edit_by_map)
btnbymap.setOnClickListener {
if (ContextCompat.checkSelfPermission(
vl.context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
vl.context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProviderClient.lastLocation.addOnSuccessListener(requireActivity()) {
location = it
val gcd = Geocoder(context, Locale.getDefault())
val addresses: List<Address> =
gcd.getFromLocationName("name", 1)
addresses[0].getAddressLine(0)
Toast.makeText(context, "${addresses}", Toast.LENGTH_LONG).show()
}
} else {
requestPermissions(
arrayOf(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
), RequestCode
)
}
}
}
我该如何解决这个问题?是否有任何替代地理编码反向?
如果你想像你说的那样从坐标中获取地址,你应该使用:
val addresses: List<Address> = geoCoder.getFromLocation(latitude, longitude, 1)
val result = addresses[0].locality
geoCoder.getFromLocationName() 当你想从字符串地址中知道纬度和经度时使用。
此外,要检索您所在位置的纬度和经度,您可以使用以下方法:
fusedLocationClient.lastLocation.addOnSuccessListener {location: Location? ->
if(location != null) {
val myLatitude = location.latitude
val myLongitude = location.longitude
}
}
因为您要求替代方案,所以我会 post 此处提供解决方法。 Google 地图是必经之路,它将根据我的经验为您提供准确地址。这使用改造来进行 Api 调用
class GetLocationDetail(addressCallBack: LocationData.AddressCallBack, context: Context) {
private val addressCallBack: LocationData.AddressCallBack
private val context: Context
fun getAddress(latitude: Double, longitude: Double, key: String) {
try {
val geocoder = Geocoder(context, Locale.getDefault())
val addresses: List<Address> = geocoder.getFromLocation(latitude, longitude, 1)
if (addresses != null && addresses.size > 0) {
val address: String =
addresses[0].getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
val city: String = addresses[0].getLocality()
val state: String = addresses[0].getAdminArea()
val country: String = addresses[0].getCountryName()
val postalCode: String = addresses[0].getPostalCode()
val knownName: String =
addresses[0].getFeatureName() // Only if available else return NULL
val locationData = LocationData()
locationData.setCity(city)
locationData.setFull_address(address)
locationData.setPincode(postalCode)
locationData.setCountry(country)
addressCallBack.locationData(locationData)
}
} catch (e: IOException) {
e.printStackTrace()
getAddressFromApi(latitude, longitude, key)
}
}
private fun getAddressFromApi(latitude: Double, longitude: Double, key: String) {
val tempBuilder = StringBuilder()
tempBuilder.append(latitude)
tempBuilder.append(",")
tempBuilder.append(longitude)
val dataService: DataService = retrofitInstance.create(
DataService::class.java
)
val stringCall: Call<String> = dataService.getData(tempBuilder.toString(), true, key)
if (stringCall.isExecuted()) {
stringCall.cancel()
}
stringCall.enqueue(object : Callback<String?>() {
fun onResponse(call: Call<String?>?, response: Response<String?>) {
try {
val jsonObject = JSONObject(response.body())
val Results: JSONArray = jsonObject.getJSONArray("results")
val zero: JSONObject = Results.getJSONObject(0)
val address_components: JSONArray = zero.getJSONArray("address_components")
val locationData = LocationData()
locationData.setFull_address(zero.getString("formatted_address"))
for (i in 0 until address_components.length()) {
val zero2: JSONObject = address_components.getJSONObject(i)
val long_name: String = zero2.getString("long_name")
val mtypes: JSONArray = zero2.getJSONArray("types")
val Type: String = mtypes.getString(0)
if (TextUtils.isEmpty(long_name) === false || long_name != null || long_name.length > 0 || long_name !== "") {
if (Type.equals("street_number", ignoreCase = true)) {
//Address1 = long_name + " ";
} else if (Type.equals("route", ignoreCase = true)) {
//Address1 = Address1 + long_name;
} else if (Type.equals("sublocality", ignoreCase = true)) {
// Address2 = long_name;
} else if (Type.equals("locality", ignoreCase = true)) {
// Address2 = Address2 + long_name + ", ";
locationData.setCity(long_name)
} else if (Type.equals(
"administrative_area_level_2",
ignoreCase = true
)
) {
// County = long_name;
} else if (Type.equals(
"administrative_area_level_1",
ignoreCase = true
)
) {
// State = long_name;
} else if (Type.equals("country", ignoreCase = true)) {
locationData.setCountry(long_name)
} else if (Type.equals("postal_code", ignoreCase = true)) {
locationData.setPincode(long_name)
}
}
}
addressCallBack.locationData(locationData)
} catch (e: JSONException) {
e.printStackTrace()
}
}
fun onFailure(call: Call<String?>?, t: Throwable) {
Log.v("response", t.toString())
}
})
}
private interface DataService {
@GET("api/geocode/json")
fun getData(
@Query("latlng") latLong: String?,
@Query("sensor") sensor: Boolean,
@Query("key") key: String?
): Call<String?>?
}
companion object {
private const val BASE_URL = "https://maps.googleapis.com/maps/"
private var retrofit: Retrofit? = null
private val retrofitInstance: Retrofit?
private get() {
if (retrofit == null) {
retrofit = Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
}
return retrofit
}
}
init {
this.addressCallBack = addressCallBack
this.context = context
}
}
所需的class位置数据
class LocationData {
var city: String? = null
var country: String? = null
var pincode: String? = null
var full_address: String? = null
interface AddressCallBack {
fun locationData(locationData: LocationData?)
}
}
我对反向地理编码有疑问。当我想将我的坐标转换为地址时,Geocoder returns 这个错误:
Caused by: java.io.IOException: grpc failed
这是我的代码:
val btnbymap = mycustomview.findViewById<Button>(R.id.edit_by_map)
btnbymap.setOnClickListener {
if (ContextCompat.checkSelfPermission(
vl.context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
vl.context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
fusedLocationProviderClient.lastLocation.addOnSuccessListener(requireActivity()) {
location = it
val gcd = Geocoder(context, Locale.getDefault())
val addresses: List<Address> =
gcd.getFromLocationName("name", 1)
addresses[0].getAddressLine(0)
Toast.makeText(context, "${addresses}", Toast.LENGTH_LONG).show()
}
} else {
requestPermissions(
arrayOf(
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION
), RequestCode
)
}
}
}
我该如何解决这个问题?是否有任何替代地理编码反向?
如果你想像你说的那样从坐标中获取地址,你应该使用:
val addresses: List<Address> = geoCoder.getFromLocation(latitude, longitude, 1)
val result = addresses[0].locality
geoCoder.getFromLocationName() 当你想从字符串地址中知道纬度和经度时使用。
此外,要检索您所在位置的纬度和经度,您可以使用以下方法:
fusedLocationClient.lastLocation.addOnSuccessListener {location: Location? ->
if(location != null) {
val myLatitude = location.latitude
val myLongitude = location.longitude
}
}
因为您要求替代方案,所以我会 post 此处提供解决方法。 Google 地图是必经之路,它将根据我的经验为您提供准确地址。这使用改造来进行 Api 调用
class GetLocationDetail(addressCallBack: LocationData.AddressCallBack, context: Context) {
private val addressCallBack: LocationData.AddressCallBack
private val context: Context
fun getAddress(latitude: Double, longitude: Double, key: String) {
try {
val geocoder = Geocoder(context, Locale.getDefault())
val addresses: List<Address> = geocoder.getFromLocation(latitude, longitude, 1)
if (addresses != null && addresses.size > 0) {
val address: String =
addresses[0].getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
val city: String = addresses[0].getLocality()
val state: String = addresses[0].getAdminArea()
val country: String = addresses[0].getCountryName()
val postalCode: String = addresses[0].getPostalCode()
val knownName: String =
addresses[0].getFeatureName() // Only if available else return NULL
val locationData = LocationData()
locationData.setCity(city)
locationData.setFull_address(address)
locationData.setPincode(postalCode)
locationData.setCountry(country)
addressCallBack.locationData(locationData)
}
} catch (e: IOException) {
e.printStackTrace()
getAddressFromApi(latitude, longitude, key)
}
}
private fun getAddressFromApi(latitude: Double, longitude: Double, key: String) {
val tempBuilder = StringBuilder()
tempBuilder.append(latitude)
tempBuilder.append(",")
tempBuilder.append(longitude)
val dataService: DataService = retrofitInstance.create(
DataService::class.java
)
val stringCall: Call<String> = dataService.getData(tempBuilder.toString(), true, key)
if (stringCall.isExecuted()) {
stringCall.cancel()
}
stringCall.enqueue(object : Callback<String?>() {
fun onResponse(call: Call<String?>?, response: Response<String?>) {
try {
val jsonObject = JSONObject(response.body())
val Results: JSONArray = jsonObject.getJSONArray("results")
val zero: JSONObject = Results.getJSONObject(0)
val address_components: JSONArray = zero.getJSONArray("address_components")
val locationData = LocationData()
locationData.setFull_address(zero.getString("formatted_address"))
for (i in 0 until address_components.length()) {
val zero2: JSONObject = address_components.getJSONObject(i)
val long_name: String = zero2.getString("long_name")
val mtypes: JSONArray = zero2.getJSONArray("types")
val Type: String = mtypes.getString(0)
if (TextUtils.isEmpty(long_name) === false || long_name != null || long_name.length > 0 || long_name !== "") {
if (Type.equals("street_number", ignoreCase = true)) {
//Address1 = long_name + " ";
} else if (Type.equals("route", ignoreCase = true)) {
//Address1 = Address1 + long_name;
} else if (Type.equals("sublocality", ignoreCase = true)) {
// Address2 = long_name;
} else if (Type.equals("locality", ignoreCase = true)) {
// Address2 = Address2 + long_name + ", ";
locationData.setCity(long_name)
} else if (Type.equals(
"administrative_area_level_2",
ignoreCase = true
)
) {
// County = long_name;
} else if (Type.equals(
"administrative_area_level_1",
ignoreCase = true
)
) {
// State = long_name;
} else if (Type.equals("country", ignoreCase = true)) {
locationData.setCountry(long_name)
} else if (Type.equals("postal_code", ignoreCase = true)) {
locationData.setPincode(long_name)
}
}
}
addressCallBack.locationData(locationData)
} catch (e: JSONException) {
e.printStackTrace()
}
}
fun onFailure(call: Call<String?>?, t: Throwable) {
Log.v("response", t.toString())
}
})
}
private interface DataService {
@GET("api/geocode/json")
fun getData(
@Query("latlng") latLong: String?,
@Query("sensor") sensor: Boolean,
@Query("key") key: String?
): Call<String?>?
}
companion object {
private const val BASE_URL = "https://maps.googleapis.com/maps/"
private var retrofit: Retrofit? = null
private val retrofitInstance: Retrofit?
private get() {
if (retrofit == null) {
retrofit = Builder()
.baseUrl(BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
}
return retrofit
}
}
init {
this.addressCallBack = addressCallBack
this.context = context
}
}
所需的class位置数据
class LocationData {
var city: String? = null
var country: String? = null
var pincode: String? = null
var full_address: String? = null
interface AddressCallBack {
fun locationData(locationData: LocationData?)
}
}