Releases: rtchagas/pingplacepicker
4.1.0
What's changed
Dependencies
- Bump to latest stable: AGP 9.2.1, AndroidX (appcompat 1.7.1, constraintlayout 2.2.1, core-ktx 1.18.0, lifecycle 2.10.0), Material 1.14.0, Places 5.2.0, coroutines 1.11.0.
- Major bumps: play-services-maps 19.0.0 → 20.0.0, Koin 3.5.6 → 4.2.1. These are transitive runtime dependencies, so consumers also using them may be pulled forward.
- Removed the unused
com.google.maps.android:android-maps-utilsdependency (it was declared but never referenced).
Internal
- Migrate the Koin viewModel DSL to
org.koin.core.module.dsl(Koin 4 moved the package).
Consuming this release
implementation("com.github.rtchagas:pingplacepicker:4.1.0")Full changelog: 4.0.1...4.1.0
4.0.1 — R8 fix for release builds
Patch release covering two issues uncovered while testing 4.0.0 against
a real consumer's R8-minified release build, plus translations for the
new autocomplete strings shipped in 4.0.0. No public API changes —
drop-in upgrade from 4.0.0.
🐛 Fixes
- Release build crashed on
Places.createClientwith
NoSuchMethodException/ServiceConfigurationError. Root cause:
the Places SDK 5.x reflectively instantiates its internal classes
via two paths — protobuf reflection (on proto messages that extend
zzbdq) and JDKServiceLoader(for gRPC name resolvers and
similar SPI providers). The SDK's shippedproguard.txtonly keeps
the proto subclass fields, so R8 strips the constructors and the
consumer's release build fails on startup. PING now ships a consumer
proguard rule that keeps every constructor of every internal Places
SDK class. Consumers get the fix automatically.
🌍 i18n
- Translate the two new
picker_autocomplete_*strings (search hint
and close-button content description) added in 4.0.0 into all 9
supported locales: ar, ca, cs, de, es-rES, ko-rKR, pt, tr, zh-rTW.
🧹 Internal cleanup
- Drop the now-unused
kotlin-parcelizeplugin (last user was
CustomPlace, removed in 4.0.0). With parcelize gone, also drop the
explicitkotlin-androidplugin and theandroid.builtInKotlin/
android.newDslopt-outs ingradle.properties— we're now on
AGP 9's built-in Kotlin support with no opt-outs.
📦 Install
dependencies {
implementation("com.google.android.libraries.places:places:5.1.1")
implementation("com.github.rtchagas:pingplacepicker:4.0.1")
}Anyone on 4.0.0 with minifyEnabled = true should upgrade — release
builds will crash on startup without this patch.
4.0.0 — Modernized on Places SDK 5.x (New)
Warning
Release builds with minifyEnabled = true crash on startup with
NoSuchMethodException inside Places.createClient. Root cause is a
missing R8 keep rule that's fixed in 4.0.1.
Use 4.0.1 instead — it's a drop-in upgrade with no API changes.
PING gets a top-to-bottom modernization. This release rewrites the picker on
top of the Places SDK for Android (New), drops the legacy Maps Web API
fallback entirely, and adopts modern Android primitives — ActivityResult
contracts, coroutines + Flow, version catalogs, Kotlin DSL build scripts.
If you're upgrading from 3.0.1, this is a breaking release.
See Migrating from 3.0.1
in the README for the full delta.
✨ Highlights
- Places SDK 5.x (New) —
searchNearby, programmatic autocomplete via
findAutocompletePredictions+fetchPlace, andfetchResolvedPhotoUri
for photos - One key path — the entire Maps Web Services fallback is gone, along
with the second API key it required - Custom autocomplete UI — replaces the now-retired
Autocompleteactivity widget with a full-screenDialogFragment
(EditText+ RecyclerView with debounced predictions) - Coroutines + Flow everywhere — RxJava2, RxAndroid, and RxBinding are
gone; ViewModels exposeStateFlow/SharedFlow, repositories are
suspend, and the UI collects with a lifecycle-scoped helper - ActivityResult contract API —
PingPlacePicker.Contractreplaces the
Builder + staticOnPlaceSelectedListenerpattern. Result survives
process death; no more leaked static listeners - Coil for the photo preview —
ivPlacePhoto.load(uri)from the new
fetchResolvedPhotoUriflow; no Bitmap allocation on the main path
🛠️ Toolchain
- AGP 9.2.0, Gradle 9.4.1, Kotlin 2.3.21, JDK 17
compileSdk/targetSdk36,minSdk24 (required by Places 5.x)- Build scripts migrated to Kotlin DSL with a
gradle/libs.versions.toml
version catalog - Permissions handled via
ActivityResultContracts.RequestMultiplePermissions
— Dexter dropped
⚠️ Breaking changes
- New launch surface:
PingPlacePicker.Builder + onActivityResult→
PingPlacePicker.Contract+registerForActivityResult OnPlaceSelectedListenerremoved — result delivered via the contracturlSigningSecret,setShouldReturnActualLatLng, and the
enable_nearby_searchboolean are gone- The "tap the map center to select an arbitrary point" interaction is gone
(it relied on Maps Web API reverse geocoding, which has no SDK 5.x equivalent) Place.Typeenum results → string place types viaplace.placeTypesplace.name/.address/.latLng→place.displayName/
.formattedAddress/.locationminSdkbumped 21 → 24
🔁 A note on enable_nearby_search
The 3.x library used this boolean to toggle between two backends —
findCurrentPlace ($30 / 1K) by default, and /nearbysearch ($40 / 1K)
when opted in. Google deprecated both in favor of the single new SDK call
searchNearby, which is what PING 4.x uses unconditionally.
The new call costs $32 / 1K at the Pro tier — $0.002 / call more than
the old default and $0.008 / call less than the old opt-in. If you relied
on the cheaper default, expect a ~7 % bump in nearby-search billing; if
you had enable_nearby_search=true, you'll actually pay less.
☁️ Cloud Console pre-req
You must enable Places API (New) on the project key — the legacy
"Places API" is not enough. searchNearby, autocomplete, and
fetchResolvedPhotoUri will return PERMISSION_DENIED otherwise.
📦 Install
dependencies {
implementation("com.google.android.libraries.places:places:5.1.1")
implementation("com.github.rtchagas:pingplacepicker:4.0.0")
}🚀 Use
private val picker = registerForActivityResult(PingPlacePicker.Contract()) { result ->
result?.let { toast("You picked ${it.place.displayName}") }
}
picker.launch(
PingPlacePicker.Request(
androidApiKey = getString(R.string.places_api_key),
mapsApiKey = getString(R.string.maps_static_api_key), // optional
),
)💸 Pricing
See the Pricing section
in the README for per-SKU rates and the free monthly allowance. With the
default field mask, a full user flow (open picker → search → confirm with
photo + static map) costs roughly $0.058 after the free tier is
exhausted.
Minor improvements
- Fixed issue #99 by exporting R8 rules to the consumer
- Bumped libs
Updated Kotlin, Gradle and libs. Breaking change to return places.
- BREAKING CHANGE: As
startActivityForResult()is deprecated now you should configure PING with aPingPlacePicker.OnPlaceSelectedListenercallback to receive the selected place. - Fixed #96 by updating
play-services-locationandplacesdependencies. - Updated Kotlin to 1.8.22
- Updated Gradle to 8.1
- Bumped all other libs
Updated to Kotlin 1.6
Updated to Kotlin 1.5
This change might brake your currently implementation.
If you are not planning to migrate to Kotlin 1.5 stay with PING 2.2.0.
- Fixes issue #88 by updating Kotlin to v1.5 and Koin to v2.2.3.
- Updated all dependencies to latest ones.
Update to Kotlin 1.4 and Koin 2.2.0
- Fixes issue #84 by updating Kotlin to v1.4
- Fixes wrong layout if target app uses ConstraintLayout 2.0.4
- Updates Koin to 2.2.2.
- Updated all dependencies to latest ones.
Minor fix adding custom name to places without name
Add a name when a custom place doesn't have one Signed-off-by: Rafael Chagas <chagas@gmail.com>
Reduce costs by completely removing Place Details calls
Completely remove calls for Place Details API Signed-off-by: Rafael Chagas <chagas@gmail.com>