5

I'm going through the process of migrating from depricated Places SDK to the Places API as described here, using the compatibility library. Everything had been working fine prior to attempting the migration. I've

1) Updated my dependencies

2) Changes my import statements

3) Min SDK was already 21

I am getting two (seemingly related) errors. cannot find symbol variable GEO_DATA_API and cannot find symbol variable GeoDataApi

the code

googleApiClient = new GoogleApiClient.Builder(PlacesActivity.this)
            .addApi(Places.GEO_DATA_API)  //***HERE***
            .enableAutoManage(this, GOOGLE_API_CLIENT_ID, this)
            .addConnectionCallbacks(this)
            .build();

and

private ArrayList<PlaceAutocomplete> getPredictions(CharSequence constraint) {
    if (googleApiClient !=null) {
        PendingResult<AutocompletePredictionBuffer> results = Places.GeoDataApi.getAutocompletePredictions(  // ***AND HERE***
                googleApiClient,
                constraint.toString(),
                latLngBounds,
                autocompleteFilter
        );

        // Wait for predictions, set the timeout.
        AutocompletePredictionBuffer autocompletePredictions = results.await(60, TimeUnit.SECONDS);

        final Status status = autocompletePredictions.getStatus();
        if (!status.isSuccess()) {
            //auto complete fail
            autocompletePredictions.release();
            return null;
        }
        //auto complete success
        Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
        ArrayList<PlaceAutocomplete> resultList = new ArrayList<>(autocompletePredictions.getCount());
        while (iterator.hasNext()) {
            AutocompletePrediction prediction = iterator.next();
            resultList.add(new PlaceAutocomplete(prediction.getPlaceId(), prediction.getFullText(null)));
        }
        // Buffer release
        autocompletePredictions.release();
        return resultList;
    }
    return null;
}
seekingStillness
  • 4,833
  • 5
  • 38
  • 68

3 Answers3

2

An entire re write of code is required. Here is working code for getting lat, lng, and name (for example)

public class MainActivity extends AppCompatActivity {
    String TAG = "placeautocomplete";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initialize Places.
    Places.initialize(getApplicationContext(), "YOUR_API_KEY");
    // Create a new Places client instance.
    PlacesClient placesClient = Places.createClient(this);

    // Initialize the AutocompleteSupportFragment.
    AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
            getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);

    // Specify the types of place data to return.
    autocompleteFragment.setPlaceFields(Arrays.asList(
         Place.Field.NAME,
         Place.Field.LAT_LNG
    ));

    // Set up a PlaceSelectionListener to handle the response.
    autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
        @Override
        public void onPlaceSelected(Place place) {
            // TODO: Get info about the selected place.
            String name = place.getName();
            double lat, lng;
            if (place.getLatLng() !=null){
                lat =place.getLatLng().latitude;
                lng =place.getLatLng().longitude;
            }

            //do something
        }

        @Override
        public void onError(Status status) {
            // TODO: Handle the error.
            Log.i(TAG, "An error occurred: " + status);
        }
    });
}
}

example xml

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <android.support.v7.widget.CardView
        android:id="@+id/idCardView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        app:cardCornerRadius="4dp"
        >
        <fragment
            android:id="@+id/autocomplete_fragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
            />
    </android.support.v7.widget.CardView>
</LinearLayout>
seekingStillness
  • 4,833
  • 5
  • 38
  • 68
0

Problem 1: cannot find symbol variable GEO_DATA_API

Solution 1: First of all lets understand the usage of Places.GEO_DATA_API

It says that "The Geo Data API provides access to getting information about places by place ID, autocompleting a user's search query by name or address, and adding new places to Google's Places database."

source (https://developers.google.com/android/reference/com/google/android/gms/location/places/GeoDataApi)

So if we want to get place information from place id then we have to use below code:

// Define a Place ID.
String placeId = "INSERT_PLACE_ID_HERE";

// Specify the fields to return (in this example all fields are returned).
List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);

// Construct a request object, passing the place ID and fields array.
FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields).build();

placesClient.fetchPlace(request).addOnSuccessListener((response) -> {
    Place place = response.getPlace();
    Log.i(TAG, "Place found: " + place.getName());
}).addOnFailureListener((exception) -> {
    if (exception instanceof ApiException) {
        ApiException apiException = (ApiException) exception;
        int statusCode = apiException.getStatusCode();
        // Handle error with given status code.
        Log.e(TAG, "Place not found: " + exception.getMessage());
    }
});

Problem 2: cannot find symbol variable GeoDataApi

Solution 2: As new places api indicates that "Use findAutocompletePredictions() to return place predictions in response to user search queries. findAutocompletePredictions() functions similarly to getAutocompletePredictions()."

source (https://developers.google.com/places/android-sdk/client-migration)

So to get auto complete predictions we can use below code:

// Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
// and once again when the user makes a selection (for example when calling fetchPlace()).
AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
// Create a RectangularBounds object.
RectangularBounds bounds = RectangularBounds.newInstance(
  new LatLng(-33.880490, 151.184363),
  new LatLng(-33.858754, 151.229596));
// Use the builder to create a FindAutocompletePredictionsRequest.
FindAutocompletePredictionsRequest request = FindAutocompletePredictionsRequest.builder()
// Call either setLocationBias() OR setLocationRestriction().
   .setLocationBias(bounds)
   //.setLocationRestriction(bounds)
   .setCountry("au")
   .setTypeFilter(TypeFilter.ADDRESS)
   .setSessionToken(token)
   .setQuery(query)
   .build();

placesClient.findAutocompletePredictions(request).addOnSuccessListener((response) -> {
   for (AutocompletePrediction prediction : response.getAutocompletePredictions()) {
       Log.i(TAG, prediction.getPlaceId());
       Log.i(TAG, prediction.getPrimaryText(null).toString());
   }
}).addOnFailureListener((exception) -> {
   if (exception instanceof ApiException) {
       ApiException apiException = (ApiException) exception;
       Log.e(TAG, "Place not found: " + apiException.getStatusCode());
   }
});
android
  • 2,942
  • 1
  • 15
  • 20
0
  1. Replace GoogleApiClient with GeoDataClient

    mGoogleApiClient = Places.getGeoDataClient(this, null);

  2. Replace AutocompletePredictionBuffer with AutocompletePredictionBufferResponse

private ArrayList getAutocomplete(CharSequence constraint) {

    if (mGoogleApiClient != null) {
        // Submit the query to the autocomplete API and retrieve a PendingResult that will
        // contain the results when the query completes.
        Task<AutocompletePredictionBufferResponse> results = mGoogleApiClient.getAutocompletePredictions(constraint.toString(), null, mPlaceFilter);

            // This method should have been called off the main UI thread. Block and wait for at most 60s
            // for a result from the API.
            try {
                Tasks.await(results, 60, TimeUnit.SECONDS);
            } catch (ExecutionException | InterruptedException | TimeoutException e) {
                Utils.handleException(e);
            }

            AutocompletePredictionBufferResponse autocompletePredictions = results.getResult();

            // Freeze the results immutable representation that can be stored safely.
            return DataBufferUtils.freezeAndClose(autocompletePredictions);
        }
        return null;
    }
thanhbinh84
  • 17,876
  • 6
  • 62
  • 69