I'm to get all nearby "point of interest" for a given latitude/longitude within a given radius without giving any search key.
I started with google place web api. But this api gives desired data when using on web only, not on android. I tried using separate keys on android for same api, even though, the place web api didn't work on android any how. It always said on android, "invalid api key".
Then I moved to google place android api. But this gives data when we use their custom UI, not in any other ways. (But I just want to get location data, not data on google's UI. Since, I want to show POI on camera).
I thought a GEO_DATA_API may help me on android. But somehow it's giving me empty result.
Here is my code for GEO_DATA_API that gave me zero result:
Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, query, bounds, null)
.setResultCallback(
new ResultCallback<AutocompletePredictionBuffer>() {
#Override
public void onResult(AutocompletePredictionBuffer buffer) {
if (buffer.getStatus().isSuccess()) {
for (AutocompletePrediction prediction : buffer) {
PlaceResult placeResult = new PlaceResult();
placeResult.setPlaceId(prediction.getPlaceId());
placeResult.setName(prediction.getFullText(null).toString());
}
}
//Prevent memory leak by releasing buffer
buffer.release();
}
}, 60, TimeUnit.SECONDS);
}
Related
I am integrated new place API and I am using the below method to get the nearest place list.
private fun getNearestPlaceList(placesClient: PlacesClient) {
val placeFields = listOf(Place.Field.NAME, Place.Field.ID, Place.Field.LAT_LNG)
val request = FindCurrentPlaceRequest.builder(placeFields).build()
placesClient.findCurrentPlace(request).addOnSuccessListener { response ->
placeList.clear()
response.placeLikelihoods.map { placeLikelihood -> placeLikelihood.place }
.filter { place -> !place.id.isNullOrEmpty() && !place.name.isNullOrEmpty() }
.forEach { place ->
val placeModel = PlaceModel(place.name!!, place.id!!)
placeList.add(placeModel)
}
setAdapter(placeList)
}.addOnFailureListener { exception ->
if (exception is ApiException) {
Log.e(TAG, "Place not found: " + exception.statusCode)
}
}
}
The current API is only collecting the nearest location of my device current location. But My requirement is to get the nearest place of a Specific(Different) location. So Is it possible to input location info(Different Lat Long) to the API and get the nearest list of that location?. Currently, the API is automatically collecting the current location and it's sending a list of nearest places. Anyone have a solution, please update?
Getting the nearest places from a specific location (not the device's current location) is not currently available in the Places SDK. To clarify, the PlaceLikelihood's from the FindCurrentPlaceResponse are places where the device is likely to be located.
The FindCurrentPlaceResponse contains a list of PlaceLikelihood
objects representing places where the device is likely to be located.
For each place, the result includes an indication of the likelihood
that the place is the right one. The list may be empty, if there is no
known place corresponding to the given device location.
As I understand your use-case, you can get a list of nearby places for a specific location through Places API - Nearby Search.
A Nearby Search lets you search for places within a specified area.
You can refine your search request by supplying keywords or specifying
the type of place you are searching for.
Sample request:
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=1500&type=restaurant&keyword=cruise&key=YOUR_API_KEY
There are also available open source client libraries that you can use for Google Maps Web Services. More info here.
Lastly, there is also an existing feature request for this in Google's Public Issue Tracker. I'd recommend you "star" it to receive updates.
https://issuetracker.google.com/issues/133276015
Hope this helps!
I'm not sure if this has been answered. This feels like such a basic question but I've been looking for a way to do this and all the examples I came across showed a list of places near the device. What I'm trying to do is to specify a location via button click, then show the places near it.
Specifically, if the user clicks button 1, this means the user wants to see the places near train station A, probably in another activity with a RecyclerView.
I was using http://www.zoftino.com/current-location-and-nearby-places-android-example for reference. I followed it all the way to adding the API key in the manifest file but I got stuck trying to analyze how I'm supposed to define a specific location instead of getting the device's location.
I'm not sure if I'm approaching this correctly but so far, I've made a Java bean that can get which station was selected...
public class Station {
String station;
public Station (String station) {
this.station = station;
}
public Station () {
}
public String getStation() {
return station;
}
public void setStation(String station) {
this.station = station;
}
I also have an activity with an onClick method to check which button was clicked...
public void onClick (View v) {
switch (v.getId()) {
case R.id.img1: station = getString(R.string.StationName1);
Log.d("project", "selected station is " + station);
break;
//other cases deleted to make this more concise
}
Station selected = new Station (station);
Log.d("project", "content of station bean is " + selected.getStation());
}
I'm testing this using a phone running Android 7.1.1. From the logcat, I know that the Station bean is able to get the selected station correctly. I honestly don't know why I decided to use getString(R.string.StationName1) but considering I'm doing this for 4 train lines and I'm already past the project's deadline. I'd rather not have to change them, if possible.
I was thinking of adding some sort of "coordinates" attribute to the Java bean and passing the exact coordinates using the switch case above but even if I did that, I still wouldn't know how to use it so I can show the nearby locations.
Edit: I'm using Android Studio 3.2.1
The linked tutorial has the following code block where places are being detected and displayed:
#SuppressLint("MissingPermission")
private void getCurrentPlaceData() {
Task<PlaceLikelihoodBufferResponse> placeResult = placeDetectionClient.
getCurrentPlace(null);
placeResult.addOnCompleteListener(new OnCompleteListener<PlaceLikelihoodBufferResponse>() {
#Override
public void onComplete(#NonNull Task<PlaceLikelihoodBufferResponse> task) {
Log.d(TAG, "current location places info");
List<Place> placesList = new ArrayList<Place>();
PlaceLikelihoodBufferResponse likelyPlaces = task.getResult();
for (PlaceLikelihood placeLikelihood : likelyPlaces) {
placesList.add(placeLikelihood.getPlace().freeze());
}
likelyPlaces.release();
PlacesRecyclerViewAdapter recyclerViewAdapter = new
PlacesRecyclerViewAdapter(placesList,
CurrentLocationNearByPlacesActivity.this);
recyclerView.setAdapter(recyclerViewAdapter);
}
});
}
Here, the getCurrentPlace method uses the current device location, which is the likely cause of your issue. In fact, the Place Detection Client documentation itself notes that: (emphasis mine)
The Place Detection API provides quick access to the device's current place, and offers the opportunity to report the location of the device at a particular place (like a check in).
Like you said, there doesn't seem to be any API in the Android Places SDK that offers a 'Nearby Places' functionality for a location. Even the above is attempting to associate the current user location with a known place (as opposed to a set of coordinates with no extra info), and doesn't seem to be meant to search for nearby places by design (though it can clearly be done).
However, the Place Search API can be used for your requirements (I have used it in an app that does something similar to what you are looking to do). It includes an endpoint for Nearby Search Requests, where a static location can be passed. The only downside is that you will have to handle the HTTP calls through Retrofit or something similar, since the SDK doesn't have an existing framework for this API.
I'm just doing a rebuild of my iOS App in Android, here and there horrible to do. One horrible part is that map thing.
I need to get places around users location by query like "park", "cafe", "bakery" etc.
In swift I just used localSearchRequest.naturalLanguageQuery
self.localSearchRequest = MKLocalSearchRequest()
self.localSearchRequest.naturalLanguageQuery = mapSearchQuery
self.localSearchRequest.region = region
self.localSearch = MKLocalSearch(request: self.localSearchRequest)
for item in localSearchResponse!.mapItems
let annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
self.mapView.addAnnotation(annotation)
}
Is there a similar way to do the same in Android by using GoogleMaps API? The only way I found was to get them via JSON from https://developers.google.com/places/web-service/search and I'm not even sure if this is for Android applications.
The GooglePlaces API for Android just list all places around a location without a way to filter them or something.
after long trying I was going with the following solution. Using the GooglePlaces webservice (link in my question):
final String PLACES_API_BASE_URL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?";
final String LOCATION_PARAM = "location";
final String RADIUS_PARAM = "radius";
final String KEYWORD_PARAM = "keyword";
final String LANGUAGE_PARAM = "language";
final String KEY_PARAM = "key";
mDestinationUri = Uri.parse(PLACES_API_BASE_URL).buildUpon()
.appendQueryParameter(LOCATION_PARAM, String.valueOf(latitude)+","+String.valueOf(longitude))
.appendQueryParameter(RADIUS_PARAM, "1000")
.appendQueryParameter(KEYWORD_PARAM, naturalLanguageQuery)
.appendQueryParameter(KEY_PARAM, "YOUR_API_KEY")
.build();
If this will accept from google we will see.
For better distinction, usage of the following APIs for Android are as follows:
Google Maps Android API to add maps to your Android app. Integrate base maps, 3D buildings, indoor floor plans, Street View and Satellite imagery, custom markers and more.
Google Places API for Android to implement device place detection, auto-complete and add information about millions of locations to your app.
And to get places around users location, try Current Place.
You can call PlaceDetectionApi.getCurrentPlace() to find the local business or other place where the device is currently located. You can optionally specify a PlaceFilter to restrict the results to one or more place IDs (up to a maximum of 10), or to select only places that are currently open. If no filter is specified, the results are not filtered.
The following code sample retrieves the list of places where the device is most likely to be located, and logs the name and likelihood for each place.
PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi
.getCurrentPlace(mGoogleApiClient, null);
result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() {
#Override
public void onResult(PlaceLikelihoodBuffer likelyPlaces) {
for (PlaceLikelihood placeLikelihood : likelyPlaces) {
Log.i(TAG, String.format("Place '%s' has likelihood: %g",
placeLikelihood.getPlace().getName(),
placeLikelihood.getLikelihood()));
}
likelyPlaces.release();
}
});
Please try going through the given documentations for more information such as regarding permissions and usage limits in using this API.
Running the code below, I create a folder with Google Drive Android API on a tablet. After a few seconds, delete that folder from a remote location on a PC. When I re-run the code, the API still thinks 'MyFolder' exists, even though it was deleted and not visible in the Google Drive app on the tablet. The folder persistance finally disappears after a while and the code works as expected. Is this expected behavior for Cloud drives?
Query query = new Query.Builder()
.addFilter(Filters.and(Filters.eq(
SearchableField.TITLE, "MyFolder"),
Filters.eq(SearchableField.TRASHED, false)))
.build();
Drive.DriveApi.query(getGoogleApiClient(), query)
.setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
#Override
public void onResult(DriveApi.MetadataBufferResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Cannot create folder in the root.");
} else {
boolean isFound = false;
for(Metadata m : result.getMetadataBuffer()) {
if(!isFound) {
if (m.getTitle().equals("MyFolder")) {
showMessage("Folder exists");
isFound = true;
}
}
}
if(!isFound) {
showMessage("Folder not found; creating it.");
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("MyFolder")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFolder(getGoogleApiClient(), changeSet)
.setResultCallback(new ResultCallback<DriveFolder.DriveFolderResult>() {
#Override
public void onResult(DriveFolder.DriveFolderResult result) {
if (!result.getStatus().isSuccess()) {
showMessage("Error while trying to create the folder");
} else {
mThwingAlbertFolderId = result.getDriveFolder().getDriveId();
showMessage("Created a folder: " + mThwingAlbertFolderId);
}
}
});
}
}
}
});
What you are seeing, is a 'normal' behavior of the GDAA, that can be explained if you look closer at the 'Lifecycle of a Drive file' diagram (warning: I've never seen the source code, just assuming from what I observed).
See, the GDAA, unlike the REST Api, creates a layer that does its best to create caching and network traffic optimization. So, when you manipulate the file/folder from the 'outside' (like the web app), the GDAA layer has no knowledge of the fact until it initiates synchronization, controlled by it's own logic. I myself originally assumed that GooDrive has this under control by dispatching some kind of notification back to the GDAA, but it apparently is not the case. Also, some Googlers mentioned 'requestSync()' as a cure, but I never succeeded to make it work.
What you think you're doing, is polling the GooDrive. But effectively, you're polling the GDAA (local GooPlaySvcs) whose DriveId is still valid (not updated), unlike the real GooDrive object that is already gone.
This is one thing that is not clearly stated in the docs. GDAA is not the best Api for EVERY application. It's caching mechanism is great for transparently managing online/offline states, network traffic optimization. battery life, ... But in your situation, you may be better off by using the REST Api, since the response you get reflects the current GooDrive state.
I myself faced a similar situation and had to switch from the GDAA back to the REST (and replaced polling with a private GCM based notification system). Needless to say, by using the REST Api, your app gets more complex, usually requiring sync adapter / service to do the data synchronization, managing network states, ... all the stuff GDAA gives you for free).
In case you want to play with the 2 apis side-by side, there are two identical CRUD implementation you can use (GDAA, REST) on Github.
Good Luck
Google drive api does not sync immediately, That is why the deleted folders are still showing, so you have to force google drive to sync using requestSync()
Drive.DriveApi.requestSync(mGoogleApiClient).await();
I fount an example snippet here:
http://wiki.workassis.com/android-google-drive-api-deleted-folder-still-exists-in-query/
As Sean mentioned, the Drive Android API caches metadata locally to reduce bandwidth and battery usage.
When you perform an action on the device, e.g. creating a folder, we attempt to apply that action on the server as soon as possible. Though there can be delays due to action dependencies and content transfers, you will generally see the results reflected on the server very quickly.
When an action is performed on the server, e.g. by deleting a folder via the web client, this action is reflected on the device the next time the Drive Android API syncs. In order to conserve battery and bandwidth, sync frequency depends on how the API is being used as this is a priority for users.
If you need to guarantee that a sync has occurred, you can explicitly request a sync using DriveApi.requestSync() and wait on the result. This is currently rate limited to 1 per minute, which is frequently hit during testing, but should have a much smaller impact on real world usage.
Please let us know on our issue tracker if this sync behavior is causing issues for your use case so we can investigate solutions.
Google drive uses its own lifecycle for Drive api and manage all things in cache that's why if you delete some file or folder and try to access using google drive apis it is still available because it is stored in cache so you need to explicitly call requestSync() method for that then after that cache will be updated and gives you that folder or file not found.
below is code for that:
Drive.DriveApi.requestSync(mGoogleApiClient).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
Log.e("sync_status", status.toString());
if (status.getStatus().isSuccess()) {
setRootFolderDriveId();
}
}
});
and don't call Drive.DriveApi.requestSync(mGoogleApiClient).await() because your main thread will block so it will crash. use above one and after get successful callback you can do your operation on google drive because it's updated.
You can do it in main thread:
Drive.DriveApi.requestSync(mGoogleApiClient).setResultCallback(new ResultCallback<com.google.android.gms.common.api.Status>() {
#Override
public void onResult(com.google.android.gms.common.api.Status status) {
if (!status.getStatus().isSuccess()) {
Log.e("SYNCING", "ERROR" + status.getStatusMessage());
} else {
Log.e("SYNCING", "SUCCESS");
// execute your code to interact with Google Drive
}
}
});
I was having the same issue and using "Drive.DriveApi.requestSync" did the trick.
Also I suggest taking a look at https://github.com/francescocervone/RxDrive because you can concatenate the sync to other drive operations using rxandroid.
For example, this becomes a delete-and-sync operation:
Observable<Boolean> deleteFile = rxDrive.delete(file);
Observable<Void> syncDrive = rxDrive.sync();
Observable.concat(deleteFile, syncDrive);
The reason why you get listed deleted files from your query is that Google Drive has a "Trash" folder that is "searchable". You need to empty your trash first.
I've got the Kinvey's Google Places functionality working pretty well, the only thing that has not been working is the fact that when my entity gets filled by my query it returns only 20 results, even if I set Query.Setlimit(100) and Query.setSkip(0)
I'm using:
Android Studio 0.6.1
Kinvey-Android-Lib 2.6.14
Kinvey-Java-2.6.14
Here is a code snippet.
Query qry = new Query(new MongoQueryFilter.MongoQueryFilterBuilder());
qry.setLimit(50);
qry.setSkip(0);
qry.nearSphere("_geoloc", marker.getPosition().latitude,
marker.getPosition().longitude, 100);
AsyncAppData<EventEntity> locs = kinveyclient.appData("locations",
EventEntity.class);
locs.get(qry, new KinveyListCallback<EventEntity>() {
#Override
public void onSuccess(EventEntity[] eventEntities) {
...
// code executes fine but eventEntities.length
always = 20 regardless of location, Limit or Skip
}
Am I missing something?
I haven't yet used the Kinvey Library but I do know from personal experience with Google Places Api the result returned is only 20 results by default. Looking at the Kinvey Docs on Location, it refers to the Google Places API.
In which it states:
By default, each Nearby Search or Text Search returns up to 20 establishment results per query; however, each search can return as many as 60 results, split across three pages. If your search will return more than 20, then the search response will include an additional value — next_page_token.