I have implemented Google Place API autocomplete functionality for my application like this: https://developers.google.com/places/training/autocomplete-android
No it just makes a Toast with that address.
How can I get the latitude and longitude from the selected address?
Use the method
public List<Address> getFromLocationName (String locationName, int maxResults) from Android Geocoder API, pass in the location name and the maximum number of results you would like and you should be good to go.
Eg.
Geocoder coder = new Geocoder(this);
try {
ArrayList<Address> adresses = (ArrayList<Address>) coder.getFromLocationName("Some Address", 10);
for(Address add : adresses){
double longitude = add.getLongitude();
double latitude = add.getLatitude();
}
} catch (IOException e) {
e.printStackTrace();
} catch(IllegalArgumentException e){
e.printStackTrace();
}
If it helps, I've recently created a library in Java for Google Places API.
Autocompletion is as simple as:
GooglePlaces client = new GooglePlace("apiKey");
List<Prediction> predictions = client.getPlacePredictions("Empire");
for (Prediction prediction : predictions) {
String description = prediction.getDescription();
// etc etc
}
And getting a latitude-longitude from an address is as simple as.
List<Place> places = client.getPlacesByQuery(address, GooglePlaces.MAXIMUM_RESULTS);
for (Place place : places) {
if (place.getAddress().equals(address)) {
double lat = place.getLatitude();
double lng = place.getLongitude();
}
}
https://github.com/windy1/google-places-api-java
You can simply use google maps api to get the lat and long
http://maps.google.com/maps/api/geocode/json?address=&sensor=false
In the above link u have to add the address next to "address=" and u can get the json data with lat and long and some other infos.
Try GeoDataClient. Refer GeoDataClient and Place IDs and details.
geoDataClient.getPlaceById(autoCompletePredictionItem.getPlaceId())
.addOnCompleteListener(new OnCompleteListener<PlaceBufferResponse>() {
#Override
public void onComplete(#NonNull Task<PlaceBufferResponse> task) {
if (task.isSuccessful()) {
PlaceBufferResponse places = task.getResult();
Place myPlace = places.get(0);
Log.e(TAG, "Place found: " + myPlace.getLatLng().toString());
places.release();
} else {
Log.e(TAG, "Place not found.");
}
}
});
According to updated documents, GeoDAtaClient is deprecated. New way is to use this:
// Define a Place ID. val placeId = "INSERT_PLACE_ID_HERE"
// Specify the fields to return. val placeFields = listOf(Place.Field.ID, Place.Field.NAME)
// Construct a request object, passing the place ID and fields array. val request = FetchPlaceRequest.newInstance(placeId, placeFields)
placesClient.fetchPlace(request)
.addOnSuccessListener { response: FetchPlaceResponse ->
val place = response.place
Log.i(PlaceDetailsActivity.TAG, "Place found: ${place.name}")
}.addOnFailureListener { exception: Exception ->
if (exception is ApiException) {
Log.e(TAG, "Place not found: ${exception.message}")
val statusCode = exception.statusCode
TODO("Handle error with given status code")
}
}
https://developers.google.com/maps/documentation/places/android-sdk/place-details#maps_places_get_place_by_id-kotlin
Related
I'm trying to get an image from latitude and longitude information using Google Place API. Is this possible?
Solution 1:
Use Geocoder for Reverse Geocoding.
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try {
List<Address> addresses = geocoder.getFromLocation(lat, lng, 1);
StringBuilder sb = new StringBuilder();
if (addresses.size() > 0) {
Address address = addresses.get(0);
for (int i = 0; i < address.getMaxAddressLineIndex(); i++)
// get Place id
}catch(Exception e){
}
}
Solution 2:
Get Place id
https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY
Then you can photos from specific place id.
public void getPhotos(String placeId){
// Specify fields. Requests for photos must always have the PHOTO_METADATAS field.
List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
// Get a Place object (this example uses fetchPlace(), but you can also use findCurrentPlace())
FetchPlaceRequest placeRequest = FetchPlaceRequest.newInstance(placeId, fields);
placesClient.fetchPlace(placeRequest).addOnSuccessListener((response) -> {
Place place = response.getPlace();
// Get the photo metadata.
PhotoMetadata photoMetadata = place.getPhotoMetadatas().get(0);
// Get the attribution text.
String attributions = photoMetadata.getAttributions();
// Create a FetchPhotoRequest.
FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata)
.setMaxWidth(500) // Optional.
.setMaxHeight(300) // Optional.
.build();
placesClient.fetchPhoto(photoRequest).addOnSuccessListener((fetchPhotoResponse) -> {
Bitmap bitmap = fetchPhotoResponse.getBitmap();
imageView.setImageBitmap(bitmap);
}).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());
}
});
});
}
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;
}
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>
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());
}
});
Replace GoogleApiClient with GeoDataClient
mGoogleApiClient = Places.getGeoDataClient(this, null);
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;
}
I am writing an Android App using Xamarin which uses Xamarin.GooglePlayServices.Maps Nuget Package. I need to get to a particular place on the map using the name of the place. For this purpose I loaded Xamarin.GooglePlayServices.Places. I am able to pass a partial place name to the GetAutocompletePredictionsAsync as so:
var autocompletePredictions = await
PlacesClass.GeoDataApi.GetAutocompletePredictionsAsync(
Adapter.googleApiClient, constraint.ToString(),
Adapter.bounds, Adapter.autoCompleteFilter);
The result I get back is basically a collection of IAutocompletePrediction. The only item in this object that has to do with location is the PlaceId. I cannot find any way to use this on the Google Maps API. I tried seeing if I could get any more information by calling the GetPlaceById:
var place = PlacesClass.GeoDataApi.GetPlaceById(googleApiClient, item.PlaceId);
But I didn't see any location information at all in that result. Does anyone know how to get LatLng information from the Google Places API?
Update: I used information from several responses to get the answer:
Task.Run(async () =>
{
PlaceBuffer places = await PlacesClass.GeoDataApi.GetPlaceByIdAsync(googleApiClient, item.PlaceId);
if (places.Status.IsSuccess)
{
foreach (var place in places)
try
{
//IPlace place = (IPlace)places.Get(0);
MarkOnMap(place.NameFormatted.ToString(), place.AddressFormatted.ToString(), place.LatLng);
UpdateCameraPosition(place.LatLng);
}
catch (Exception ex)
{
Log.Error("WhatNow", ex.ToString());
}
}
places.Dispose();
});
The odd thing was when I enumerated the places in the foreach, the place was an IPlace type. However
IPlace place = (IPlace)places.Get(0);
Did not cast to an IPlace. Who knows? I just hope that Dispose() releases the buffer as recommended in the Docs. Xamarin is always just a little different from Java.
Thanks to everyone who helped.
I have used this, you can try this code.
I am using autoCompleteTextView.
dropLocationEt.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceAutoCompleteAdapter.PlaceAutocomplete item = mAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(TAG, "Autocomplete item selected: " + item.description);
/*
Issue a request to the Places Geo Data API to retrieve a Place object with additional
details about the place.
*/
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(googleApiClient, placeId);
placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
// Request did not complete successfully
Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());
places.release();
return;
}
// Get the Place object from the buffer.
final Place place = places.get(0);
latLngDrop = place.getLatLng();
StaticMethods.hideKeyboard(getActivity());
dropLocationEt.setSelection(0);
}
});
}
});
From the latlngDrop, you can retrieve the lat and lng, eg: latlngDrop.getLatitude, latlngDrop.getLongitude
i'm using for firts time Retrofit on my Android app.
This is the structure of json object that i have to retrive:
{
"placemarks":[
{
"address":"Via di Santa Maria a Marignolle, 15, 50124 Firenze",
"coordinates":[
11.23348,
43.75855,
0
],
"engineType":"CE",
"exterior":"GOOD",
"fuel":100,
"interior":"GOOD",
"name":"049/EV284TP",
"smartPhoneRequired":false,
"vin":"WME4513341K774636"
}
]
}
i have write this Pojo model for object "placemarks" and all otehr items.
And i have write this code to retrive the json data and put it into map:
private void getPlacemark(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.car2go.com/api/v2.1/vehicles?loc=roma&oauth_consumer_key=roadzapp&format=json")
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
Call<ResponsePlacemarks> call = service.getPlacemark();
call.enqueue(new Callback<ResponsePlacemarks>() {
#Override
public void onResponse(Response<ResponsePlacemarks> response, Retrofit retrofit) {
Log.d("response: ", String.valueOf(response.body()));
try {
mMap.clear();
// This loop will go through all the results and add marker on each location.
for (int i = 0; i < response.body().getPlacemarks().size(); i++) {
Double lat = response.body().getPlacemarks().get(i).getCoordinates().get(1);
Double lng = response.body().getPlacemarks().get(i).getCoordinates().get(0);
String placeName = response.body().getPlacemarks().get(i).getAddress();
MarkerOptions markerOptions = new MarkerOptions();
LatLng latLng = new LatLng(lat, lng);
// Position of Marker on Map
markerOptions.position(latLng);
// Adding Title to the Marker
markerOptions.title(placeName);
// Adding Marker to the Camera.
Marker m = mMap.addMarker(markerOptions);
// Adding colour to the marker
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
// move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
}
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
}
});
}
but now when i run app the json are note load and i have error in the first line of for loop:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List android.mobility.com.mobiity.model.ResponsePlacemarks.getPlacemarks()' on a null object reference
Hi have found the error.
On APIService i have set #GET method in this way: #GET(".") because i use as URL the URL into BaseURL. So if i set all url into #GET the method works fine.
How i can use only the url into BaseULRalso into #GET?
First, you can only call response.body() exactly once.
So, comment this.
// Log.d("response: ", String.valueOf(response.body()));
And extract that list variable
final ResponsePlacemarks _response = response.body();
final List<Placemark> placemarks = _response.getPlacemarks();
for (int i = 0; i < placemarks.size(); i++) {
final Placemark p = placemarks.get(i);
Coordinates c = p.getCoordinates();
Double lat = c.get(1);
Double lng = c.get(0);
String placeName = p.getAddress();
And if that doesn't work, then you need for the Java object to exactly match the JSON response, otherwise it is null
How i can use only the url into BaseULRalso into #GET?
Your base URL should look like something this
https://www.car2go.com/api/v2.1
Then you should be able to have something like
#GET("/vehicles")
public ResponsePlacemarks getVehicles(
#Query("oauth_consumer_key") String key,
#Query("format") String format
#Query("loc") String loc
);
public ResponsePlacemarks getVehicles(String loc) {
return getVehicles("roadzapp", "json", loc);
}
Or maybe just
#GET("/vehicles?format=json")
public ResponsePlacemarks getVehicles(
#Query("oauth_consumer_key") String key,
#Query("loc") String loc
);
The reason for putting the key into the method call is that you shouldn't store the key as a string on your device for security reasons.
Most likely your POJO does not match the JSON structure.
Can you post your POJO class and how are you deserializing the JSON?
I am following http://examples.javacodegeeks.com/android/android-google-places-autocomplete-api-example/ this tutorial to get google place autocomplete in my app,
Now that it is working fine but I need to keep the place suggestion country specific, I have tried giving country like india , china but it is not showing any result.
Could you please help me out and tell where should I need to change the code to get it done.
Thanks,
Prashant
From Documentation for Places API
To get a list of predicted place names and/or addresses, call
GeoDataApi.getAutocompletePredictions(), passing the following
parameters:
Required: A query string containing the text typed by the user.
Required: A LatLngBounds object, restricting the results to a specific
area specified by latitude and longitude bounds.
When making request
You can specify bounds for India.
This can serve you
String apiKey = getString(R.string.places_api_key);
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), apiKey);
PlacesClient placesClient = Places.createClient(this);
}else{
Toast.makeText(PlaceAutocompleteActivity.this, "-----initialize-----", Toast.LENGTH_LONG).show();
}
// Initialize the AutocompleteSupportFragment.
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
// PlaceFields
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG));
// autocompleteFragment.setOnPlaceSelectedListener(MapsActivity.this);
try {
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(#NonNull Place place) {
displayLocation(place.getLatLng().latitude,place.getLatLng().longitude,place.getName());
Toast.makeText(getApplicationContext(), "getName: " + place.getName() + " getLatLng: "+ place.getLatLng(), Toast.LENGTH_LONG).show();
// Intent i = Intent(this, idnow.se MainActivity.class);
// i.putExtra("getLatLng",place.getLatLng());
// startActivity(i);
// finish();
}
#Override
public void onError(#NonNull Status status) {
Toast.makeText(getApplicationContext(), "" + status.toString(), Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
Toast.makeText(PlaceAutocompleteActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
// PlaceFields - HERE
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG));
https://github.com/EddyEU/GooglePlaceAutocomplete