das web wird mobil - geolocation und location based services
DESCRIPTION
Vortrag auf der International PHP Conference 2012 Spring Edition zu Geolocation im Browser und Location Based Services wie Google Places und FoursquareTRANSCRIPT
das web wird mobilStephan Schmidt, 1&1 Internet AG
International PHP Conference 2012Hotel Maritim proArte, Berlin
beiArbeit
Sport
und Spiel
ich suche cup-cakes in meiner nähe.
schritt eins:wo bin ich?
geolocation vor dem jahr 2008:
91.22.203.142
where the heck is oberderdingen?
google weiß ziemlich genau wo* ich bin.
* und zwar nicht in oberderdingen.
geolocation im jahr 2012:
48.96977,8.613199
geographische breite
geographische länge
längengrade
breitengrade
woher weiß mein browser das?
geolocation api
+
und etwas Magie!
die Magie ist aus javascript nutz-bar.
if (navigator.geolocation) { navigator.geolocation.getCurrentPosition ( function(position) { // location retrieved }, function(error) { // error happened } );}
Geoposition coords : Coordinates accuracy : 65 // meter altitude : null altitudeAccuracy : null heading : null latitude : 52.518328398571434 longitude : 13.387145829999998 speed : null
PositionError code : 1 constructor : PositionErrorConstructor PERMISSION_DENIED : 1 POSITION_UNAVAILABLE : 2 TIMEOUT : 3 message: "User denied Geolocation"
navigator.geolocation.getCurrentPosition( function(position) {...}, function(error) {...}, { enableHighAccuracy : true, timeout : 5000, // milliseconds maximumAge : 1000 * 60 // milliseconds } );}
navigator.geolocation.watchPosition ( function(pos) { // position changed }, function(error) { // error happened })
9.0+ 3.5+ 5.0+ 5.0+ 10.6+
3.0+ 2.0+
where the heck is 52.51832,13.387145?
var latlon = new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude);var options = { zoom: 15, center: latlon, mapTypeId: google.maps.MapTypeId.ROADMAP};var map = new google.maps.Map($("#map"), options);
var marker = new google.maps.Marker({ position: latlon, map: map, title:"Sie sind hier!"});
menschen wollen lieber adressen.
http://maps.google.com/maps/api/service/output?latlng=lat,lon&sensor=false
http://maps.google.com/maps/api/service/output?latlng=lat,lon&sensor=false
geocode
http://maps.google.com/maps/api/service/output?latlng=lat,lon&sensor=false
xml | json
http://maps.google.com/maps/api/service/output?latlng=lat,lon&sensor=false
position
genug javascript, jetzt kommt der elefant.
public function geocodeReverse($lat, $lon) { $url = sprintf('http://maps.google.com/maps/api/' . 'geocode/json?latlng=%s,%s&sensor=false', $lat, $lon); $json = file_get_contents($url); $response = json_decode($json);
if ($response->status === 'OK') { return $response->results; } else { throw new Exception($response->status); } }
"results" : [ { "address_components" : [...], "formatted_address" : "Mittelstraße 23, 10117 Berlin, Germany", "geometry" : { "location" : { "lat" : 52.51820, "lng" : 13.387170 }, "location_type" : "ROOFTOP", "viewport" : { "northeast" : {...}, "southwest" : {...} } }, "types" : [ "street_address" ] }, { "address_components" : [ ... ], "formatted_address" : "10117 Berlin, Germany", "geometry" : { "bounds" : {...} }, "location" : {...}, "location_type" : "APPROXIMATE", "viewport" : {...}, "types" : [ "postal_code" ] }, ...]
try { $geocoder = new Geocoder(); $results = $geocoder->geocodeReverse($lat, $lon);
echo "<ul>"; foreach ($results as $result) { printf("<li>%s (%s)</li>", $result->formatted_address, implode(', ', $result->types)); } echo "</ul>";} catch (Exception $e) { echo "Geocodierung ist fehlgeschlagen: " . $e->getMessage();}
•Mittelstraße 23, 10117 Berlin, Germany (street_address)
•10117 Berlin, Germany (postal_code)
•Mitte, Berlin, Germany (sublocality, political)
•Berlin, Germany (locality, political)
•Berlin, Germany (administrative_area_level_1, political)
•Germany (country, political)
Laut Google:
Mittelstraße 2310117 BerlinGermany
Laut Hotel:
Friedrichstraße 15110117 BerlinGermany
schritt zwei:wo sind die cupcakes?
https:/maps.googleapis.com/maps/api/place/method/output?parameters&key=[key]
https:/maps.googleapis.com/maps/api/place/method/output?parameters&key=[key]
sicherheit
https:/maps.googleapis.com/maps/api/place/method/output?parameters&key=[key]
search | detail
https:/maps.googleapis.com/maps/api/place/method/output?parameters&key=[key]
xml | json
locationradiussensor
keywordnametypes
rankbylanguage
https://maps.googleapis.com/maps/api/place/search/json?location=52.5185,13.3885&types=food&radius=25000&key=...&sensor=false&name=cupcake
{ "html_attributions" : [ "Listings by ...." ], "results" : [ { "geometry" : { "location" : { "lat" : 52.5107460, "lng" : 13.4577320 } }, "icon" : "http://maps.gstatic.com/ma...s/restaurant-71.png", "id" : "b9a03f408df6ade6021a150d3bf5ae04f24853db", "name" : "Cupcake", "rating" : 4.10, "reference" : "CnRl...R7TAHjPh_H2Mw", "types" : [ "store", "cafe", "restaurant", "food"], "vicinity" : "Krossener Straße 12, Berlin" }, ....], "status" : "OK"}
$config = parse_ini_file('google-places.ini');
$long = $_GET['long'];$lat = $_GET['lat'];
$searchUrl = sprintf("https://maps.....search/json". "?location=%s,%s&types=food&radius=25000&“. "key=%s&sensor=false", $lat, $long, $config['googlekey']);
if (isset($_GET['search'])) { $searchUrl = $searchUrl . "&name=" . $_GET['search'];}
$jsonResponse = file_get_contents($searchUrl);$response = json_decode($jsonResponse);
if ($response->status !== 'OK') { printf('<p>Es ist ein Fehler aufgetreten: %s</p>', $response->status);} else { print '<ul style="float: left; margin-right: 25px;">'; foreach ($response->results as $entry) { $rating = isset($entry->rating) ? $entry->rating : 0; print '<li>'; printf('<a href="google-detail.php?reference=%s">%s</a>'. '<div class="rating_bar" title="Bewertung: %s"> '. '<div style="width:%d%%"></div></div>', $entry->reference, $entry->name, $rating, $rating/5*100); print '</li>'; } print '</ul>';}
schritt zwei ½:wie weit ist es noch?
ba c
die erde ist eine kugel*.
* eigentlich ein ellipsoid.
dist = 6378.388 * acos( sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1))
http://www.kompf.de/gps/distcalc.html
function calcDistance($lat1, $lon1, $lat2, $lon2) { $lat1 = deg2rad($lat1); $lon1 = deg2rad($lon1); $lat2 = deg2rad($lat2); $lon2 = deg2rad($lon2); return 6378.388 * acos(sin($lat1) * sin($lat2) + cos($lat1) * cos($lat2) * cos($lon2 - $lon1));}
geht das auch ohne google?
https://api.foursquare.com/v2/venues/search?intent=browse&ll=lat,lon&radius=10000&limit=15&query=Cupcake&client_id=[id]&client_secret=[secret]&v=20111113
https://api.foursquare.com/v2/venues/search?intent=browse&ll=lat,lon&radius=10000&limit=15&query=Cupcake&client_id=[id]&client_secret=[secret]&v=20111113
sicherheit
https://api.foursquare.com/v2/venues/search?intent=browse&ll=lat,lon&radius=10000&limit=15&query=Cupcake&client_id=[id]&client_secret=[secret]&v=20111113
versionierung
https://api.foursquare.com/v2/venues/search?intent=browse&ll=lat,lon&radius=10000&limit=15&query=Cupcake&client_id=[id]&client_secret=[secret]&v=20111113
position
$config = parse_ini_file('config/foursquare-config.ini');$searchUrl = sprintf('https://....../venues/search?'. 'intent=browse&ll=%s,%s&radius=10000&limit=15'. '&query=Cupcake&client_id=%s&client_secret=%s'. '&v=20111113', $lat, $long, $config['clientId'], $config['clientSecret']);
$jsonResponse = file_get_contents($searchUrl);$response = json_decode($jsonResponse);
foreach ($response->response->venues as $venue) { printf("<li>%s (%0.2f km)</li>", $venue->name, $venue->location->distance/1000);}
"categories": [ { "id" : "4bf58dd8d48988d1bc941735", "name" : "Cupcake Shop", "pluralName" : "Cupcake Shops", "shortName" : "Cupcakes", "icon" : { "prefix" : "https://.../categories/food/cupcakes_", "sizes" : [32,44,64,88,256], "name" : ".png" }, "primary" : true } ]
personalisierte empfehlungen
wie unterstützt das mein business?
Beware of the Dark Side, Luke.
http://www.cultofmac.com/157641/this-creepy-app-isnt-just-stalking-women-without-their-knowledge-its-a-wake-up-call-about-facebook-privacy/