Skip to content

Commit 6210c6d

Browse files
authored
fix(tutorials): migrate CurrentPlaceDetailsOnMap to Places SDK 6 (#2456)
Places SDK for Android 6.0 removed Places.initialize and PlacesClient.findCurrentPlace, which both CurrentPlaceDetailsOnMap tutorials relied on. Use Places.initializeWithNewPlacesApiEnabled and searchNearby around the device's last-known location instead. The tutorials were not part of the root build, so the breakage went unnoticed. Include them in settings.gradle.kts, the build-tutorials CI job and verify_all.sh, and fix the build files so they compile with the shared version catalog and current AGP.
1 parent 704b5e6 commit 6210c6d

10 files changed

Lines changed: 113 additions & 83 deletions

File tree

‎.github/workflows/build.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ jobs:
143143
- name: Build and check
144144
run: |
145145
./gradlew :tutorials:kotlin:Polygons:assembleDebug
146+
./gradlew :tutorials:java:CurrentPlaceDetailsOnMap:assembleDebug
147+
./gradlew :tutorials:kotlin:CurrentPlaceDetailsOnMap:assembleDebug
146148
147149
test:
148150
runs-on: ubuntu-latest

‎scripts/verify_all.sh‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ MODULES=(
4747
":snippets:java-app"
4848
":snippets:app-utils"
4949
":tutorials:kotlin:Polygons"
50+
":tutorials:java:CurrentPlaceDetailsOnMap"
51+
":tutorials:kotlin:CurrentPlaceDetailsOnMap"
5052
)
5153

5254
# Parse arguments

‎settings.gradle.kts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ project(":snippets:app-places-ktx").projectDir = file("snippets/app-places-ktx")
6969
// Tutorials
7070
include(":tutorials:kotlin:Polygons")
7171
project(":tutorials:kotlin:Polygons").projectDir = file("tutorials/kotlin/Polygons/app")
72+
include(":tutorials:java:CurrentPlaceDetailsOnMap")
73+
project(":tutorials:java:CurrentPlaceDetailsOnMap").projectDir = file("tutorials/java/CurrentPlaceDetailsOnMap/app")
74+
include(":tutorials:kotlin:CurrentPlaceDetailsOnMap")
75+
project(":tutorials:kotlin:CurrentPlaceDetailsOnMap").projectDir = file("tutorials/kotlin/CurrentPlaceDetailsOnMap/app")
7276
// Add others as needed, starting with these for now
7377

7478
// Visual Testing

‎tutorials/java/CurrentPlaceDetailsOnMap/README.md‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This sample goes hand in hand with a tutorial for the Google Maps Android API:
77
Prerequisites
88
--------------
99

10-
- Android API level 21+
10+
- Android API level 24+
1111
- Latest Android Build Tools
1212
- Android Support Repository
1313
- Google Repository
@@ -28,6 +28,17 @@ This sample uses the Gradle build system.
2828

2929
This demo app requires that you add your own Google Maps API key. See [Get an API key](https://developers.google.com/maps/documentation/android-sdk/get-api-key) for more instructions.
3030

31+
The app uses the Places SDK for Android (New), so the API key must have
32+
[Places API (New)](https://developers.google.com/maps/documentation/places/android-sdk/cloud-setup)
33+
enabled in addition to the Maps SDK for Android.
34+
35+
This sample is part of the root Gradle build. From the root of this repository, add your key to
36+
`secrets.properties` (see `local.defaults.properties` for the format) and run:
37+
38+
```
39+
./gradlew :tutorials:java:CurrentPlaceDetailsOnMap:assembleDebug
40+
```
41+
3142
Support
3243
-------
3344

‎tutorials/java/CurrentPlaceDetailsOnMap/app/build.gradle.kts‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ android {
4040
}
4141
release {
4242
isMinifyEnabled = false
43-
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
43+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
4444
}
4545
}
4646

@@ -49,11 +49,12 @@ android {
4949

5050
dependencies {
5151
implementation(libs.appcompat)
52-
implementation(libs.playServicesMaps)
52+
implementation(libs.play.services.maps)
53+
implementation(libs.play.services.location)
5354
implementation(libs.places)
5455
implementation(libs.volley)
55-
implementation(platform(libs.kotlinBom))
56-
implementation (libs.material)
56+
implementation(platform(libs.kotlin.bom))
57+
implementation(libs.material)
5758
testImplementation(libs.junit)
5859
}
5960

‎tutorials/java/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java‎

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@
4242
import com.google.android.gms.tasks.OnCompleteListener;
4343
import com.google.android.gms.tasks.Task;
4444
import com.google.android.libraries.places.api.Places;
45+
import com.google.android.libraries.places.api.model.CircularBounds;
4546
import com.google.android.libraries.places.api.model.Place;
46-
import com.google.android.libraries.places.api.model.PlaceLikelihood;
47-
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
48-
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
4947
import com.google.android.libraries.places.api.net.PlacesClient;
48+
import com.google.android.libraries.places.api.net.SearchNearbyRequest;
49+
import com.google.android.libraries.places.api.net.SearchNearbyResponse;
5050
import java.util.Arrays;
5151
import java.util.List;
5252

@@ -82,6 +82,7 @@ public class MapsActivityCurrentPlace extends AppCompatActivity implements OnMap
8282

8383
// Used for selecting the current place.
8484
private static final int M_MAX_ENTRIES = 5;
85+
private static final double SEARCH_RADIUS_METERS = 100.0;
8586
private String[] likelyPlaceNames;
8687
private String[] likelyPlaceAddresses;
8788
private List[] likelyPlaceAttributions;
@@ -107,7 +108,7 @@ protected void onCreate(Bundle savedInstanceState) {
107108

108109
// [START_EXCLUDE silent]
109110
// Construct a PlacesClient
110-
Places.initialize(getApplicationContext(), BuildConfig.PLACES_API_KEY);
111+
Places.initializeWithNewPlacesApiEnabled(getApplicationContext(), BuildConfig.MAPS_API_KEY);
111112
placesClient = Places.createClient(this);
112113

113114
// Construct a FusedLocationProviderClient.
@@ -323,52 +324,55 @@ private void showCurrentPlace() {
323324
if (locationPermissionGranted) {
324325
// Use fields to define the data types to return.
325326
List<Place.Field> placeFields =
326-
Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG);
327-
328-
// Use the builder to create a FindCurrentPlaceRequest.
329-
FindCurrentPlaceRequest request = FindCurrentPlaceRequest.newInstance(placeFields);
327+
Arrays.asList(
328+
Place.Field.DISPLAY_NAME,
329+
Place.Field.FORMATTED_ADDRESS,
330+
Place.Field.LOCATION);
331+
332+
// Search around the device's last-known location, falling back to the center of the
333+
// map if the location is not available yet.
334+
LatLng center =
335+
lastKnownLocation != null
336+
? new LatLng(
337+
lastKnownLocation.getLatitude(),
338+
lastKnownLocation.getLongitude())
339+
: map.getCameraPosition().target;
340+
CircularBounds searchArea = CircularBounds.newInstance(center, SEARCH_RADIUS_METERS);
341+
342+
// Use the builder to create a SearchNearbyRequest that returns the closest places
343+
// first.
344+
SearchNearbyRequest request =
345+
SearchNearbyRequest.builder(searchArea, placeFields)
346+
.setMaxResultCount(M_MAX_ENTRIES)
347+
.setRankPreference(SearchNearbyRequest.RankPreference.DISTANCE)
348+
.build();
330349

331350
// Get the likely places - that is, the businesses and other points of interest that
332-
// are the best match for the device's current location.
333-
@SuppressWarnings("MissingPermission")
334-
final Task<FindCurrentPlaceResponse> placeResult =
335-
placesClient.findCurrentPlace(request);
351+
// are closest to the device's current location.
352+
final Task<SearchNearbyResponse> placeResult = placesClient.searchNearby(request);
336353
placeResult.addOnCompleteListener(
337-
new OnCompleteListener<FindCurrentPlaceResponse>() {
354+
new OnCompleteListener<SearchNearbyResponse>() {
338355
@Override
339-
public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
356+
public void onComplete(@NonNull Task<SearchNearbyResponse> task) {
340357
if (task.isSuccessful() && task.getResult() != null) {
341-
FindCurrentPlaceResponse likelyPlaces = task.getResult();
358+
List<Place> likelyPlaces = task.getResult().getPlaces();
342359

343360
// Set the count, handling cases where less than 5 entries are
344361
// returned.
345-
int count;
346-
if (likelyPlaces.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
347-
count = likelyPlaces.getPlaceLikelihoods().size();
348-
} else {
349-
count = M_MAX_ENTRIES;
350-
}
362+
int count = Math.min(likelyPlaces.size(), M_MAX_ENTRIES);
351363

352-
int i = 0;
353364
likelyPlaceNames = new String[count];
354365
likelyPlaceAddresses = new String[count];
355366
likelyPlaceAttributions = new List[count];
356367
likelyPlaceLatLngs = new LatLng[count];
357368

358-
for (PlaceLikelihood placeLikelihood :
359-
likelyPlaces.getPlaceLikelihoods()) {
369+
for (int i = 0; i < count; i++) {
360370
// Build a list of likely places to show the user.
361-
likelyPlaceNames[i] = placeLikelihood.getPlace().getName();
362-
likelyPlaceAddresses[i] =
363-
placeLikelihood.getPlace().getAddress();
364-
likelyPlaceAttributions[i] =
365-
placeLikelihood.getPlace().getAttributions();
366-
likelyPlaceLatLngs[i] = placeLikelihood.getPlace().getLatLng();
367-
368-
i++;
369-
if (i > (count - 1)) {
370-
break;
371-
}
371+
Place place = likelyPlaces.get(i);
372+
likelyPlaceNames[i] = place.getDisplayName();
373+
likelyPlaceAddresses[i] = place.getFormattedAddress();
374+
likelyPlaceAttributions[i] = place.getAttributions();
375+
likelyPlaceLatLngs[i] = place.getLocation();
372376
}
373377

374378
// Show a dialog offering the user the list of likely places, and
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
MAPS_API_KEY=DEFAULT_API_KEY
2-
PLACES_API_KEY=DEFAULT_API_KEY

‎tutorials/kotlin/CurrentPlaceDetailsOnMap/README.md‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This sample goes hand in hand with a tutorial for the Google Maps Android API:
77
Prerequisites
88
--------------
99

10-
- Android API level 21+
10+
- Android API level 24+
1111
- Latest Android Build Tools
1212

1313
Getting started
@@ -25,6 +25,17 @@ This sample uses the Gradle build system.
2525

2626
This demo app requires that you add your own Google Maps API key. See [Get an API key](https://developers.google.com/maps/documentation/android-sdk/get-api-key) for more instructions.
2727

28+
The app uses the Places SDK for Android (New), so the API key must have
29+
[Places API (New)](https://developers.google.com/maps/documentation/places/android-sdk/cloud-setup)
30+
enabled in addition to the Maps SDK for Android.
31+
32+
This sample is part of the root Gradle build. From the root of this repository, add your key to
33+
`secrets.properties` (see `local.defaults.properties` for the format) and run:
34+
35+
```
36+
./gradlew :tutorials:kotlin:CurrentPlaceDetailsOnMap:assembleDebug
37+
```
38+
2839
Support
2940
-------
3041

‎tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle.kts‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ android {
3030
targetSdk = libs.versions.targetSdk.get().toInt()
3131
versionCode = libs.versions.versionCode.get().toInt()
3232
versionName = libs.versions.versionName.get()
33-
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
33+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
3434
}
3535

3636
buildFeatures {
@@ -43,7 +43,7 @@ android {
4343
}
4444
release {
4545
isMinifyEnabled = false
46-
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
46+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
4747
}
4848
}
4949

@@ -62,16 +62,16 @@ kotlin {
6262
}
6363

6464
dependencies {
65-
androidTestImplementation(libs.espressoCore) {
65+
androidTestImplementation(libs.espresso.core) {
6666
exclude(group = "com.android.support", module = "support-annotations")
6767
}
6868
implementation(libs.appcompat)
69-
implementation(libs.playServicesMaps)
69+
implementation(libs.play.services.maps)
70+
implementation(libs.play.services.location)
7071
implementation(libs.places)
7172
implementation(libs.volley)
7273
testImplementation(libs.junit)
73-
implementation(libs.coreKtx)
74-
implementation(libs.lifecycleViewModelKtx)
74+
implementation(libs.core.ktx)
7575
implementation(libs.kotlin.stdlib)
7676
implementation(libs.material)
7777
}

‎tutorials/kotlin/CurrentPlaceDetailsOnMap/app/src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.kt‎

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ import com.google.android.gms.maps.model.LatLng
4141
import com.google.android.gms.maps.model.Marker
4242
import com.google.android.gms.maps.model.MarkerOptions
4343
import com.google.android.libraries.places.api.Places
44+
import com.google.android.libraries.places.api.model.CircularBounds
4445
import com.google.android.libraries.places.api.model.Place
45-
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest
4646
import com.google.android.libraries.places.api.net.PlacesClient
47+
import com.google.android.libraries.places.api.net.SearchNearbyRequest
4748

4849
/**
4950
* An activity that displays a map showing the place at the device's current location.
@@ -92,7 +93,7 @@ class MapsActivityCurrentPlace :
9293

9394
// [START_EXCLUDE silent]
9495
// Construct a PlacesClient
95-
Places.initialize(applicationContext, BuildConfig.MAPS_API_KEY)
96+
Places.initializeWithNewPlacesApiEnabled(applicationContext, BuildConfig.MAPS_API_KEY)
9697
placesClient = Places.createClient(this)
9798

9899
// Construct a FusedLocationProviderClient.
@@ -288,47 +289,41 @@ class MapsActivityCurrentPlace :
288289
* current place on the map - provided the user has granted location permission.
289290
*/
290291
// [START maps_current_place_show_current_place]
291-
@SuppressLint("MissingPermission")
292292
private fun showCurrentPlace() {
293-
if (map == null) {
294-
return
295-
}
293+
val map = map ?: return
296294
if (locationPermissionGranted) {
297295
// Use fields to define the data types to return.
298-
val placeFields = listOf(Place.Field.NAME, Place.Field.ADDRESS, Place.Field.LAT_LNG)
296+
val placeFields = listOf(
297+
Place.Field.DISPLAY_NAME,
298+
Place.Field.FORMATTED_ADDRESS,
299+
Place.Field.LOCATION,
300+
)
301+
302+
// Search around the device's last-known location, falling back to the center of
303+
// the map if the location is not available yet.
304+
val center = lastKnownLocation?.let { LatLng(it.latitude, it.longitude) }
305+
?: map.cameraPosition.target
306+
val searchArea = CircularBounds.newInstance(center, SEARCH_RADIUS_METERS)
299307

300-
// Use the builder to create a FindCurrentPlaceRequest.
301-
val request = FindCurrentPlaceRequest.newInstance(placeFields)
308+
// Use the builder to create a SearchNearbyRequest that returns the closest places
309+
// first.
310+
val request = SearchNearbyRequest.builder(searchArea, placeFields)
311+
.setMaxResultCount(M_MAX_ENTRIES)
312+
.setRankPreference(SearchNearbyRequest.RankPreference.DISTANCE)
313+
.build()
302314

303315
// Get the likely places - that is, the businesses and other points of interest that
304-
// are the best match for the device's current location.
305-
val placeResult = placesClient.findCurrentPlace(request)
316+
// are closest to the device's current location.
317+
val placeResult = placesClient.searchNearby(request)
306318
placeResult.addOnCompleteListener { task ->
307319
if (task.isSuccessful && task.result != null) {
308-
val likelyPlaces = task.result
320+
val likelyPlaces = task.result.places.take(M_MAX_ENTRIES)
309321

310-
// Set the count, handling cases where less than 5 entries are returned.
311-
val count = if (likelyPlaces != null && likelyPlaces.placeLikelihoods.size < M_MAX_ENTRIES) {
312-
likelyPlaces.placeLikelihoods.size
313-
} else {
314-
M_MAX_ENTRIES
315-
}
316-
var i = 0
317-
likelyPlaceNames = arrayOfNulls(count)
318-
likelyPlaceAddresses = arrayOfNulls(count)
319-
likelyPlaceAttributions = arrayOfNulls<List<*>?>(count)
320-
likelyPlaceLatLngs = arrayOfNulls(count)
321-
for (placeLikelihood in likelyPlaces?.placeLikelihoods ?: emptyList()) {
322-
// Build a list of likely places to show the user.
323-
likelyPlaceNames[i] = placeLikelihood.place.name
324-
likelyPlaceAddresses[i] = placeLikelihood.place.address
325-
likelyPlaceAttributions[i] = placeLikelihood.place.attributions
326-
likelyPlaceLatLngs[i] = placeLikelihood.place.latLng
327-
i++
328-
if (i > count - 1) {
329-
break
330-
}
331-
}
322+
// Build a list of likely places to show the user.
323+
likelyPlaceNames = likelyPlaces.map { it.displayName }.toTypedArray()
324+
likelyPlaceAddresses = likelyPlaces.map { it.formattedAddress }.toTypedArray()
325+
likelyPlaceAttributions = likelyPlaces.map { it.attributions }.toTypedArray()
326+
likelyPlaceLatLngs = likelyPlaces.map { it.location }.toTypedArray()
332327

333328
// Show a dialog offering the user the list of likely places, and add a
334329
// marker at the selected place.
@@ -342,7 +337,7 @@ class MapsActivityCurrentPlace :
342337
Log.i(TAG, "The user did not grant location permission.")
343338

344339
// Add a default marker, because the user hasn't selected a place.
345-
map?.addMarker(
340+
map.addMarker(
346341
MarkerOptions()
347342
.title(getString(R.string.default_info_title))
348343
.position(defaultLocation)
@@ -440,5 +435,6 @@ class MapsActivityCurrentPlace :
440435

441436
// Used for selecting the current place.
442437
private const val M_MAX_ENTRIES = 5
438+
private const val SEARCH_RADIUS_METERS = 100.0
443439
}
444440
}

0 commit comments

Comments
 (0)