'Geocoder.GeocodeListener listener'
但该新构造函数需要 API 级别 33 及以上。对于较低的 API 级别我该怎么办,解决方案是什么?
官方文档 - 使用 getFromLocation(double, double, int, android.location.Geocoder.GeocodeListener) 来避免阻塞等待结果的线程。
示例:
//Variables
val local = Locale("en_us", "United States")
val geocoder = Geocoder(this, local)
val latitude = 18.185600
val longitude = 76.041702
val maxResult = 1
//Fetch address from location
geocoder.getFromLocation(latitude,longitude,maxResult,object : Geocoder.GeocodeListener{
override fun onGeocode(addresses: MutableList<Address>) {
// code
}
override fun onError(errorMessage: String?) {
super.onError(errorMessage)
}
})
@Suppress("DEPRECATION")
fun Geocoder.getAddress(
latitude: Double,
longitude: Double,
address: (android.location.Address?) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getFromLocation(latitude, longitude, 1) { address(it.firstOrNull()) }
return
}
try {
address(getFromLocation(latitude, longitude, 1)?.firstOrNull())
} catch(e: Exception) {
//will catch if there is an internet problem
address(null)
}
}
这就是如何使用:
Geocoder(requireContext(), Locale("in"))
.getAddress(latlng.latitude, latlng.longitude) { address: android.location.Address? ->
if (address != null) {
//do your logic
}
}
lowerLeftLatitude
、
lowerLeftLongitude
、
upperRightLatitude
、
upperRightLongitude
。将“边界框”设置为视图边界坐标应该可以。
@SuppressWarnings({"deprecation", "RedundantSuppression"})
...
Geocoder geoCoder = new Geocoder(requireContext());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
geoCoder.getFromLocationName(
geocode, maxResults,
lowerLeftLatitude, lowerLeftLongitude,
upperRightLatitude,upperRightLongitude,
addresses -> {
Address bestMatch = (addresses.isEmpty() ? null : addresses.get(0));
updatePosition(item, bestMatch);
});
} else {
try {
List<Address> addresses = geoCoder.getFromLocationName(geocode, maxResults);
Address bestMatch = (addresses.isEmpty() ? null : addresses.get(0));
updatePosition(item, bestMatch);
} catch (IOException e) {
if (mDebug) {Log.e(LOG_TAG, e.getMessage());}
}
}
我所做的是将 Geocoder 代码移至 Runnable 类,并将该代码作为其自己的线程执行,如下所示:
GeocoderThread geocoderThread = new GeocoderThread(latitude, longitude, this);
Thread gcThread = new Thread(geocoderThread);
gcThread.start();
try{
gcThread.join();
}
catch(InterruptedException e1) {
e1.printStackTrace();
}
city = geocoderThread.getCity();
这是我的 Runnable 类:
public class GeocoderThread implements Runnable{
Geocoder geo;
double latitude;
double longitude;
String city;
public GeocoderThread(double lat, double lon, Context ctx) {
latitude = lat;
longitude = lon;
geo = new Geocoder(ctx, Locale.getDefault());
}
@Override
public void run() {
try
{
//deprecated, need to put this in a runnable thread
List<Address> address = geo.getFromLocation(latitude, longitude, 2);
if(address.size() > 0)
{
city = address.get(0).getLocality();
}
}
catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
catch (NullPointerException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
public String getCity() {
return city;
}
}
private suspend fun Geocoder.getAddress(
latitude: Double,
longitude: Double,
): Address? = withContext(dispatcherProvider.IO) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
suspendCoroutine { cont ->
getFromLocation(latitude, longitude, 1) {
cont.resume(it.firstOrNull())
}
}
} else {
suspendCoroutine { cont ->
@Suppress("DEPRECATION")
val address = getFromLocation(latitude, longitude, 1)?.firstOrNull()
cont.resume(address)
}
}
} catch (e: Exception) {
Timber.e(e)
null
}
}