Skip to content

[geocoding_android] Run pre-API 33 geocoder lookups off the main thread - #331

Draft
luanbatistadev wants to merge 1 commit into
Baseflow:mainfrom
luanbatistadev:fix/android-pre-api33-geocoder-off-main-thread
Draft

luanbatistadev wants to merge 1 commit into
Baseflow:mainfrom
luanbatistadev:fix/android-pre-api33-geocoder-off-main-thread

Conversation

@luanbatistadev

Copy link
Copy Markdown

On Android 12 and lower (API < 33), placemarkFromCoordinates and locationFromAddress go through getFromLocationPreAndroidApi33 / getFromLocationNamePreAndroidApi33. Both are synchronous Pigeon host methods, so the blocking Geocoder.getFromLocation / Geocoder.getFromLocationName call runs on the platform main thread. When the geocoding service is slow (poor network, busy LocationManager), the main thread waits on a binder call and the app gets an ANR.

We see this in production on Android 11 devices. The main thread stack of the ANR:

at android.os.BinderProxy.transact (BinderProxy.java:540)
at android.location.ILocationManager$Stub$Proxy.getFromLocation (ILocationManager.java:1486)
at android.location.Geocoder.getFromLocation (Geocoder.java:133)
at <GeocoderProxyApi.getFromLocationPreAndroidApi33>
at <Pigeon message handler>
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Looper.loop (Looper.java:250)
at android.app.ActivityThread.main (ActivityThread.java:7806)

The same calls also show up as non-fatal TimeoutException: Waited 5 seconds ... ReverseGeocode errors from Geocoder.getFromLocationPreAndroidApi33.

Change

  • Mark both pre-API 33 methods @async in pigeons/geocoder.dart and regenerate the bindings with Pigeon 26.1.2. The Dart API is unchanged (the methods already returned a Future).
  • GeocoderProxyApi now runs the blocking lookup on a single background thread and delivers the result (or the error) back on the main thread through ProxyApiRegistrar.runOnMainThread, so the reply and the Address proxy instances are still created on the main thread.
  • The API 33+ listener-based methods are untouched.

Most of the diff in the generated files is ordering only: regenerating from the current pigeons/geocoder.dart emits GeographicBounds after Geocoder, which differs from the checked-in output. The functional change in the generated code is the async signature of the two methods.

Pre-launch Checklist

  • I made sure the project builds. (The Kotlin was not compiled locally; I am relying on the example build in CI. I'll mark this ready once CI is green.)
  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • This PR only changes one package (or documents why an exception is needed).
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy, or this PR does not need version changes.
  • I updated CHANGELOG.md with a new ## x.y.z section that matches the version in pubspec.yaml
  • I updated/added relevant documentation (doc comments with ///).
  • I rebased onto main.
  • I added new tests to check the change I am making, or this PR does not need tests. (The package has no native unit tests to extend.)
  • I made sure all existing and new tests are passing.
  • I ran dart format . and committed any changes.
  • I ran flutter analyze and fixed any errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant