Геокодер — getFromLocation() устарел

Я получил сообщение о том, что эта функция (или ее конструктор) устарела. Есть новый конструктор этой функции, который принимает дополнительный параметр'Geocoder.GeocodeListener listener'но для этого нового конструктора требуется уровень API 33 и выше. Что мне делать для более низких уровней API, какое решение?

4 ответа

Я думаю, что самый чистый способ справиться с этим устареванием - это переместить getFromLocation в новую функцию расширения и добавить @Suppress("DEPRECATION") следующим образом:

      @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
        }
    }

Поскольку это устарело на уровне API 33, я считаю, что это единственный вариант для более низких уровней API.

Я адаптировал код @Eko Yulianto, чтобы избежать необходимости раскрывать обратный вызов.

      private suspend fun Geocoder.getAddress(
    latitude: Double,
    longitude: Double,
): Address? = withContext(Dispatchers.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
    }
}

Недавно у меня возникла проблема, из-за которой я продолжал получать исключение Java.IO.IOException: сбой grpc.

Я переместил этот код геокодера в класс 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;
    }
}
Другие вопросы по тегам