10

I've received a message that this function (or it's constructor) has been deprecated. There's a new constructor of that function that accepts an additional parameter 'Geocoder.GeocodeListener listener' but that new constructor requires an API Level 33 and above. What should I do for the lower API levels, what's the solution?

enter image description here

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
Stefan
  • 2,829
  • 5
  • 20
  • 44
  • 1
    The warning is incorrect, that is the way to go on lower SDKs. You can just ignore it. Also see https://stackoverflow.com/questions/50675122/i-keep-getting-deprecated-api-warning-even-with-correct-check – user3738870 Aug 23 '22 at 10:17

5 Answers5

9

The Official Doc - Use getFromLocation(double, double, int, android.location.Geocoder.GeocodeListener) instead to avoid blocking a thread waiting for results.

Example:

//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)

 }

})
Sachin
  • 1,307
  • 13
  • 23
5

Since this is deprecated in API level 33, I believe this is the only option for lower API levels.

Ahmad Bhatti
  • 189
  • 1
  • 8
4

I think the cleanest way to handle this deprecation is move getFromLocation into new extension function and add @Suppress("DEPRECATION") like this :

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

And this is how to use :

    Geocoder(requireContext(), Locale("in"))
        .getAddress(latlng.latitude, latlng.longitude) { address: android.location.Address? ->
        if (address != null) {
            //do your logic
        }
    }
Eko Yulianto
  • 145
  • 2
  • 5
0

Method getFromLocationName still exists, but now expects "bounding box" parameters lowerLeftLatitude, lowerLeftLongitude, upperRightLatitude, upperRightLongitude.
Setting the "bounding box" to the view boundary coordinates should work.

@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());}
    }
}
Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • The other method signature without bounding box parameters still exists: https://developer.android.com/reference/android/location/Geocoder#getFromLocationName(java.lang.String,%20int,%20android.location.Geocoder.GeocodeListener) – Jose_GD Aug 28 '23 at 23:08
0

I had an issue recently where I kept getting Java.IO.IOException: grpc failed.

What I did was move that Geocoder code to a Runnable class and execute that code as its own Thread like so:

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();

And this is my Runnable class:

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;
    }
}
Karim O.
  • 1,325
  • 6
  • 22
  • 36