This my code:
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocationName(text, 10);
test.clear();
for (int i = 0; i < addresses.size(); i++) {
Address address = addresses.get(i);
for (int j=0;j<address.getMaxAddressLineIndex();j++) {
test.add(address.getAddressLine(j) + ", " + address.getCountryName());
// address.getLatitude();
// address.getLatitude();
}
}
But I can't find something like address.getPlaceID().
Maybe I use another API get PlaceID from name, or lat, long from above code. Thanks!
Look at this docs.
You will get the lat,long,name for the Address
and then call this below google api
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=cruise&key=YOUR_API_KEY
You will get a response like this
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : -33.870775,
"lng" : 151.199025
}
},
...
"place_id" : "ChIJrTLr-GyuEmsRBfy61i59si0",
...
}
],
"status" : "OK"
}
For there you will get the place-id.
Note: Please enable the GeoLocation Api from Google Developer Console otherwise it return the error msg :This API project is not authorized to use this API.
You also can use direct search instead of nearbysearch
https://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&key=YOUR_API_KEY
Look at Getting Started with Geocoding
Both of the proposed ways cost money and I think peoples should mention it. We have the -$200 from the Google, but its all depends from how much users you have and how frequent you need to use the geocode. 60k requests per month to the geocoder - easy $300 only for to use the geocode https API :
Nov 1 – 30, 2018
Geocoding API Geocoding: 6073 Counts - $30.38
Dont filter what you need in the responses, like we have in the requests from other posts? Expect way more:
Nov 1 – 30, 2018
Places API Places Details: 2389 Counts $40.61
Nov 1 – 30, 2018
Places API Contact Data: 2385 Counts $7.17
Nov 1 – 30, 2018
Places API Atmosphere Data: 2385 Counts $11.95
I do recommend to use get the Place Id like this. It would be better than call the API directly.
I stumble for this issue all day. so I hope that it would be help. who're finding the way out to get place ID from your current location.
for android
Kotlin
val mPlaceDetectionClient = Places.getPlaceDetectionClient(this.context!!)
val placeResult = mPlaceDetectionClient.getCurrentPlace(null)
placeResult.addOnCompleteListener(object : OnCompleteListener<PlaceLikelihoodBufferResponse>{
override fun onComplete(p0: Task<PlaceLikelihoodBufferResponse>) {
val likelyPlaces = p0.result
if(likelyPlaces.any()){
// get the place ID from code below
placeId = likelyPlaces[0].place.id }
}
})
or if who are implementing or developing on another language such a java. you can implement your code according to a reference below.
java
https://developers.google.com/places/android-sdk/googleapi-migration
Related
I'm working on a project and I'm using some old google maps stuff. It requires longitude and latitude gps coordinates to get the location of a hospital for example.
I can't find a way to retrieve that info in this format 'lng,lat'
For example: (34.417514, 8.7518123)
The only thing the new google maps has is plus codes (used by https://plus.codes/) which they use as the location coordinates.
Can you guys help me find out a way to convert them to lng lat format or a way to retrieve the lng and lat from Google Maps website directly.
Or an alternative by saving my geolocation in a plus codes format in android studio (in a database of course) instead of using lat lng
https://www.up-00.com/i/00125/m4kadq6c7aeb.png
You can convert Plus Codes into lat/lng format via Plus codes API. If you have full (8-digits before "+" character, e.g. 8F6CCQCW+2F for your location) Plus Code, you can locally (without any internet request) use OpenLocationCode.decode() method this way:
...
OpenLocationCode olc = new OpenLocationCode("8F6CCQCW+2F");
Log.d(TAG, "Lat = " + olc.decode().getCenterLatitude() + " Lng = " + olc.decode().getCenterLongitude());
...
If you have short Plus Code (less than 8 digits before "+" character, e.g. CCQCW+2F Gafsa for your location, Gafsa is the area and it's used instead of using the full plus code) you can use HttpURLConnection with
`https://plus.codes/api?address=CCQCW%2B2F Gafsa&key=YOUR_GEOCODING_API_KEY`
(%2B is for the for + symbol)
(NB! you need Geocoding API Key for geocode Gafsa part, which is the area, you need an area with a short plus code)
and get location.lat and location.lng tags from its JSON response:
{
"plus_code": {
"global_code": "8F6CCQJG+",
"geometry": {
"bounds": {
"northeast": {
"lat": 34.432500000000005,
"lng": 8.777500000000003
},
"southwest": {
"lat": 34.43000000000001,
"lng": 8.775000000000006
}
},
"location": {
"lat": 34.431250000000006,
"lng": 8.776250000000005
}
},
"locality": {}
},
"status": "OK"
}
For "alternative" (saving my geolocation in a plus codes format) you can (fully local) use encode() method of OpenLocationCode class:
OpenLocationCode.encode(34.43125, 8.77625)
Python solution:
>>> import openlocationcode
>>> openlocationcode.decode('8F6CCQCW+2F')
[34.42, 8.796125, 34.420125, 8.79625, 34.4200625, 8.7961875, 10]
Python implementation
from openlocationcode import openlocationcode as olc
olc.decode("8F6CCQCW+2F")
Output:
[34.42, 8.796125, 34.420125, 8.79625, 34.4200625, 8.7961875, 10]
I am making an app that displays daily stock data to the user. The problem is, I am using retrofit to make the API calls. With this type of JSON, I would need a POJO with every stock symbol. This obviously isn't possible.
I want to be able to do something along the lines of - listOfStocks[1].getQuote().getLatestPrice();
This is the kind of JSON data that I am receiving.
{
"AAPL":{
"quote":{
"symbol":"AAPL",
"companyName":"Apple Inc.",
"primaryExchange":"Nasdaq Global Select",
"sector":"Technology",
"calculationPrice":"close",
"open":156.21,
"openTime":1548772200635,
"close":154.68,
"closeTime":1548795600703,
"high":158.13,
"low":154.11,
"latestPrice":154.68,
"latestSource":"Close",
"latestTime":"January 29, 2019",
"latestUpdate":1548795600703,
"latestVolume":39402866,
"iexRealtimePrice":161.04,
"iexRealtimeSize":90,
"iexLastUpdated":1548799005088,
"delayedPrice":154.68,
"delayedPriceTime":1548795600703,
"extendedPrice":160.6,
"extendedChange":5.92,
"extendedChangePercent":0.03827,
"extendedPriceTime":1548799199389,
"previousClose":156.3,
"change":-1.62,
"changePercent":-0.01036,
"iexMarketPercent":0.02338,
"iexVolume":921239,
"avgTotalVolume":42308638,
"iexBidPrice":0,
"iexBidSize":0,
"iexAskPrice":0,
"iexAskSize":0,
"marketCap":731605928040,
"peRatio":13.03,
"week52High":233.47,
"week52Low":142,
"ytdChange":-0.030876717325227843
}
},
"FB":{
"quote":{
"symbol":"FB",
"companyName":"Facebook Inc.",
"primaryExchange":"Nasdaq Global Select",
"sector":"Technology",
"calculationPrice":"close",
"open":148,
"openTime":1548772200837,
"close":144.19,
"closeTime":1548795600692,
"high":148.1,
"low":143.43,
"latestPrice":144.19,
"latestSource":"Close",
"latestTime":"January 29, 2019",
"latestUpdate":1548795600692,
"latestVolume":17353892,
"iexRealtimePrice":144.25,
"iexRealtimeSize":100,
"iexLastUpdated":1548796485236,
"delayedPrice":144.19,
"delayedPriceTime":1548795600692,
"extendedPrice":145.05,
"extendedChange":0.86,
"extendedChangePercent":0.00596,
"extendedPriceTime":1548799197301,
"previousClose":147.47,
"change":-3.28,
"changePercent":-0.02224,
"iexMarketPercent":0.02505,
"iexVolume":434715,
"avgTotalVolume":25773532,
"iexBidPrice":0,
"iexBidSize":0,
"iexAskPrice":0,
"iexAskSize":0,
"marketCap":414371435774,
"peRatio":19.51,
"week52High":218.62,
"week52Low":123.02,
"ytdChange":0.04048110849056598
}
},
"MSFT":{
"quote":{
"symbol":"MSFT",
"companyName":"Microsoft Corporation",
"primaryExchange":"Nasdaq Global Select",
"sector":"Technology",
"calculationPrice":"close",
"open":104.88,
"openTime":1548772200862,
"close":102.94,
"closeTime":1548795600515,
"high":104.97,
"low":102.17,
"latestPrice":102.94,
"latestSource":"Close",
"latestTime":"January 29, 2019",
"latestUpdate":1548795600515,
"latestVolume":31105047,
"iexRealtimePrice":102.895,
"iexRealtimeSize":100,
"iexLastUpdated":1548795598662,
"delayedPrice":102.94,
"delayedPriceTime":1548795600515,
"extendedPrice":103.67,
"extendedChange":0.73,
"extendedChangePercent":0.00709,
"extendedPriceTime":1548799195514,
"previousClose":105.08,
"change":-2.14,
"changePercent":-0.02037,
"iexMarketPercent":0.03309,
"iexVolume":1029266,
"avgTotalVolume":40670438,
"iexBidPrice":0,
"iexBidSize":0,
"iexAskPrice":0,
"iexAskSize":0,
"marketCap":790189956684,
"peRatio":26.53,
"week52High":116.18,
"week52Low":83.83,
"ytdChange":-0.002371582278481079
}
}
}
Personally I'd make a model for quote and symbol then use a Map<String, Symbol>.
Here's an example where the model only has the latestPrice property to shorten the example:
class Quote {
#SerializedName("latestPrice")
private double latestPrice;
// ...
}
class Symbol {
#SerializedName("quote")
private Quote quote;
//...
}
Now making the Retrofit call use Map<String, Symbol> should give you a map where you can iterate over the entries and get the latest price of each of them.
I am creating an Android App , an Uber Clone. In this I am using Firebase to list the rides created by the user.
The Ride stored in the following format .
{
"category" : "NUVO",
"driverids" : "",
"drop_lat" : "40.7127753",
"drop_long" : "-74.0059728",
"estdate" : "Wed#Feb#28th",
"estmile" : "4.19",
"esttime" : "01:02#PM",
"esttotalfare" : "4.61",
"fareest" : "1.1",
"g" : "t9z83wv46x",
"l" : [ 40.674426, -73.944033 ],
"notes" : "Gv",
"orgin_lat" : "145 Brooklyn Ave, Brooklyn, NY 11213, USA%20New York, NY, USA",
"request_id" : "5a75579740d166e95b8b4567",
"requested_category" : "FAM_SUV",
"rider_id" : "5a507bf340d16660288b4567",
"status" : 1,
"trip_id" : 0
}
Now I am Using GeoFire's GeoQuery's queryAtLocation to pick all rides with in 5 KMs from his current location.
The query uses the lat & lang from the field "l" and compare it with the current location lat & lang of the driver.
If the list's lat & lang is within 5 KMs , it will return the key , that is the parent name of the child "l".
Now I am currently in India. I use Lockito App to fix a Mock GPS location in India. After that I create a Ride within 5 KMs radius.
Now , the ride successfully listed in the drivers list. No Problem.
My Issue
But When I fix a mock GPS location in USA , this flow not working. I fixed the driver location on Brookyln Childeren's Museum and also created a ride on the same museum. But GeoQuery not calling onKeyEntered . It simply exists after calling GeoQueryReady function .
I check my current Lat & Lang from the app and it returns as 40.67434763453142,-73.94402358680964. I checked this against the lat&lang on field "l" .(refer above JSON). Both pointing to same location.
But GeoQuery failed to retrieve it
My Question
Why this issue happening ?. If I use India's locations. Geoquery works perfectly .
But why it failing in USA.
You may tell ,"There will be an issue in lockito". But Lockito returning correct location lat lang . I checked it in Logcat. And , if there is a issue in Lockitto then How it working in India.
Here My GeoQoery Code :
try {
showDialog();
double nearByDistanceRadius = 5.00d;
com.firebase.geofire.GeoFire geoFire = new com.firebase.geofire.GeoFire(FirebaseDatabase.getInstance().getReference().child(childtype));
final com.firebase.geofire.GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), nearByDistanceRadius);
geoQueryEventListener=new GeoQueryEventListener() {
#Override
public void onKeyEntered(final String key, GeoLocation location) {
Toast.makeText (getApplicationContext(), "The key is = ",Toast.LENGTH_LONG).show();
}
#Override
public void onKeyExited(final String key) {
System.out.println("ON KEYEXITED"+key);
}
#Override
public void onKeyMoved(String key, GeoLocation location) {
System.out.println("ON KEYMOVED"+key);
}
#Override
public void onGeoQueryReady() {
System.out.println("ON KEYQUERYREADY");
#Override
public void onGeoQueryError(DatabaseError error) {
System.out.println("ON KEYERROR"+error);
}
};
geoQuery.addGeoQueryEventListener(geoQueryEventListener);
} catch (Exception e) {
e.printStackTrace();
}
Above , except onGeoQueryReady , no method called if I use USA. But it's
working in India. Can anyone tell me why that is the case?
This maybe long gone n dusted but perhaps can help others.
Since u mention its mock GPS coordinates. and u probably manually entered them.
GeoFire uses a special g: "code" (10 digit code) which is area wise / city wise
if you use the same g code in the same city / country (India in ur case) it will work fine !
However,if you use the same code in another country , geoQuery will fail. To make it work. u need to add one line in your code
geoFire.SetLocation() and someone in USA needs to run that code once only. geoFire will save a special key in g: "" Location. After you have the key you can remove that line from your app.
You can use that key generated by geoFire to manually enter as many locations as you want in USA and geoQuery will always work on that !!! Make sure you use the same pattern as geoFire does.
g:
l:
0:
1:
It took a while but I figured. It's that buggy geofire dependency. Downgrade from 3.0.0 to 2.3.1 solved it.
I'm trying to parse in android studio a JSON, that containts this :
"stops":
[
{
"num": 1,
"time": "2016-04-27T06:15:00.000Z",
"title":"Flight to London",
"desc":"Barcelona BCN-London-Gatwick LGW",
"type":"0",
"subtype":0
},
{
"num": 2,
"time": "2016-04-27T10:35:00.000Z",
"title":"Gatwick express",
"desc":"From Airport to London",
"type":"0",
"subtype":1
},
{
"num": 3,
"time": "2016-04-27T12:15:00.000Z",
"title":"Pub the black horse",
"desc":"From Airport to London",
"type":1,
"subtype":1,
"location": "51.476334, -0.062700",
"images": [ "https://fitzrovianews.files.wordpress.com/2011/01/black_horse_rathbone_pl.jpg"
]
},
{
"num": 4,
"time": "2016-04-27T12:16:47.000Z",
"title":"The Tower Bridge",
"desc":"# The Tower Bridge Facts\n## Architecture\n**Tower Bridge** is a combined bascule and suspension bridge in London built in _1886–1894_. The bridge crosses the River Thames close to the Tower of London and has become an iconic symbol of London. Tower Bridge is one of five London bridges now owned and maintained by the Bridge House Estates, a charitable trust overseen by the City of London Corporation. \n>It is the only one of the Trust's bridges not to connect the City of London directly to the Southwark bank, as its northern landfall is in Tower Hamlets.\n## The bridge Exhibition\nThis must-see London attraction invites you to step inside the most famous bridge in the world to explore its iconic structure, spectacular views and glass floor, modern exhibitions and magnificent Victorian Engine Rooms! ",
"type":1,
"subtype":6,
"location": "51.507792, -0.087786",
"images": [
"https://i.ytimg.com/vi/nby0Mr2LfBQ/hqdefault.jpg",
"http://raindropsofsapphire.com/wp-content/uploads/2011/10/london-bridge.jpg",
"http://www.londonforfree.net/gizmo/wp-content/uploads/2015/02/southwark-bridge.jpg"
]
},
{
"num": 5,
"time": "2016-04-27T12:18:10.000Z",
"title":"St. Paul Cathedral",
"desc":"# HISTORY \nSt **Paul's Cathedral**, London, is an _Anglican cathedral_, the seat of the _Bishop of London_ and the mother church of the Diocese of London. \n * It sits on Ludgate Hill at the highest point of the City of London and is a Grade 1 listed building. \n * Its dedication to Paul the Apostle dates back to the original church on this site, founded in AD 604.",
"type":1,
"subtype":6,
"location": "51.513825, -0.098351",
"images": [
"https://d1wgio6yfhqlw1.cloudfront.net/sysimages/product/resized6/Interior_St_Pauls_Cathedral_132_12992.jpg",
"https://d1kioxk2jrdjp.cloudfront.net/resized/486x324/48-st_pauls_ctahedral_millenirm_bridge.jpg",
"http://i4.mirror.co.uk/incoming/article8299330.ece/ALTERNATES/s615b/LOND-2016-052-HMQ-St-Pauls-Thanks-Giving-704JPG.jpg"
]
}
]
The problem is, i don't know how to deal with the field "location" or "images" which are optional. I know how to deal with the first "stop", i'm doing this :
JSONArray stops = jsonObj.getJSONArray("stops");
for (int i = 0; i < stops.length(); i++) {
JSONObject c = stops.getJSONObject(i);
String num = c.getString("num");
String time = c.getString("time");
String title = c.getString("title");
String descripcion = c.getString("desc");
String type = c.getString("type");
String subtype = c.getString("subtype");
......
}
But i don't know how to check it here is a elment location or a jsonArray "images"...
best way to handle optional fields in JSON is to use opt instead of get
opt provides the parsed value if exist or default value for that datatype if requested key does not exist.
best thing is, it don't even need a try catch block since it always returns a value and in case of any error from server, it will not let your app crash or prevent other values from being parsed.
String location = response.optString("location");
if location exist in response, then it will initialize with the value or it will leave the string null. in case of int or long default is 0, in case of boolean default is false. read about opt for more details.
Use has() method
JSONArray stops = jsonObj.getJSONArray("stops");
for (int i = 0; i < stops.length(); i++) {
JSONObject c = stops.getJSONObject(i);
String num = c.getString("num");
String time = c.getString("time");
String title = c.getString("title");
String descripcion = c.getString("desc");
String type = c.getString("type");
String subtype = c.getString("subtype");
if(c.has("location") && !c.isNull("location")){
// parse location
}
if(c.has("images") && !c.isNull("images")){
// parse images
}
.....
}
you should use Retrofit and Google Gson, where you do not have to do lot of work,
they will do the job for you.
look at these
https://guides.codepath.com/android/Consuming-APIs-with-Retrofit
http://www.vogella.com/tutorials/Retrofit/article.html
I am trying to get pincode for longitude and latitude using google location services. I used geocoder to get the Address Object. I see that in for some address getPostalCode is Null but postal code can be seen in the address lines.
How do I get the postal code in this case? Should i use regex to get it?
Based from this documentation, you need to specify the restriction by using the componentRestrictions parameter and can be filter by postalCode or country.
The following example function demonstrates using the componentRestrictions parameter to filter by country and postalCode:
function codeAddress() {
geocoder.geocode({
componentRestrictions: {
country: 'AU',
postalCode: '2000'
}
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
window.alert('Geocode was not successful for the following reason: ' + status);
}
});
}
You can check this example in GitHub.