Google released its Places API last month (July 2010) and this is exciting news for developers. Why? Because, as developers, we have access to an extremely important database of information, allowing us to develop compelling mobile applications that publish a mobile user’s location, and provide information on places that are in proximity to that location.
This will open up innovative thinking for businesses trying to attract more customers, and enhance the services of existing customers.
As developers, we have a great opportunity to move mobile application development from cheap Soundboard applications, to powerful, business savvy applications capable of legitimizing mobile’s presence as a significant business contributor.
I plan to discuss all details required for you to get started developing these truly innovative mobile applications on the Android platform.
And as a bonus, I will discuss the difference between Proximity Alert and Location-based Mobile Applications, and how the two can be combined to create an even higher level of innovation. We will discuss these details in the last part.
Let’s get started with Part 1 to identify the items we need to complete before we can develop using the Places API. If you’re wondering if it’s more involved than the other API’s. You’re right. It is!
Requirements for Using Google’s Places API
The easy answer is that you need to fill out a registration form. However, you will notice that an Adsense publisher id is required, and you may not have this. Don’t fret. You can fill out the application here to obtain your Adsense account. It may take several days to get approved, so be patient.
BTW, Once you have your Adsense account, you can register to use Google’s Places API by filling out this registration form.
Additionally, say you want to track your Adsense performance using URL Channels. The aforementioned link will provide all the information you need.
Required: Google Map API Key
In order to use Google’s Places API, you will need to register and obtain a Google Map’s API Key. I created a post detailing exactly how to do this found here.
Getting Familiar with URL Authentication
Requests to certain Maps API web services now require digital signatures using a cryptographic key. In fact, all Places API service requests require URL Authentication. Click here to learn more.
Getting Familiar with Place Searches and Place Details
Per Google, and I quote
The Google Places API is a service that returns information about a “place” (hereafter referred to as a Place) — defined within this API as an establishment, a geographic location, or prominent point of interest — using an HTTP request. Place requests specify locations as latitude/longitude coordinates.
Two basic Place requests are available: a Place Search request and a Place Details request. Generally, a Place Search request is used to return candidate matches, while a Place Details request returns more specific information about a Place.
This service is designed for processing place requests generated by a user for placement of application content on a map; this service is not designed to respond to batch of offline queries, which are a violation of its terms of use.
As a developer, keep in mind that you usually first obtain a list of places that satisfy your filter, and allow a user drill-down into the details of a specific place. Thus the existence of the two API’s.
Getting Familiar Calling the Places API
In general, calls to the Places API are made as follows. This is an example of a call to the Place Search Service, and the client Id and signature are intentionally supplied as invalid:
// JSON: http://maps.google.com/maps/api/place/search/json?location=40.717859,-73.9577937&radius=1600&client=clientId&sensor=true_or_false&signature=SIGNATURE // XML: http://maps.google.com/maps/api/place/search/xml?location=40.717859,-73.9577937&radius=1600&client=clientId&sensor=true_or_false&signature=SIGNATURE
This is asking for places for about a mile around Williamsburg, Brooklyn.
And you can expect a response formatted in JSON as follows:
{
"status": "OK",
"results": [ {
"name": "Williamsburg",
"types": [ "locality", "political" ],
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"reference": "ClRBAAAAXP...lHAPyHom2aG"
}, {
"name": "Greenpoint",
"vicinity": "New York",
"types": [ "neighborhood", "political" ],
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png",
"reference": "CkQ_AAAAhd...MF45fwr44Ek"
}, {
"name": "Peter Luger Steakhouse",
"vicinity": "Broadway, Brooklyn",
"types": [ "restaurant", "food", "establishment" ],
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
"reference": "ClRCAAAAt3...6Nt7k11iQdT"
}, {
"name": "Music Hall of Williamsburg",
"vicinity": "North 6th Street, Brooklyn",
"types": [ "establishment" ],
"icon": "http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
"reference": "ClRFAAAAN...6UOKCbjv7Sxy"
},
...additional results ...
],
"html_attributions": [ ]
}
Or in XML as follows:
<PlaceSearchResponse> <status>OK</status> <result> <name>Williamsburg</name> <type>locality</type> <type>political</type> <icon>http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png</icon> <reference>CkRAAAAAUhZG...Yy0b4-sd1zCUu9P8</reference> </result> <result> <name>Greenpoint</name> <vicinity>New York</vicinity> <type>neighborhood</type> <type>political</type> <icon>http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png</icon> <reference>CkQ-AAAAHIDo...nYmSR8l52FmkMH6c</reference> <name>Peter Luger Steakhouse</name> <vicinity>Broadway, Brooklyn</vicinity> <type>restaurant</type> <type>food</type> <type>establishment</type> <icon>http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png</icon> <reference>ClRBAAAATIpR...mHSxoyiRcr_FVuww</reference> </result> ...additional results... </PlaceSearchResponse>
In order to make a valid call, you are required to encrypt your URL with your private key and attach result as your signature. Note that the call above excluded a valid client Id and signature. In java, for example, you can create your signature as follows:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class UrlSigner {
// Note: Generally, you should store your private key someplace safe
// and read them into your code
private static String keyString = "YOUR_PRIVATE_KEY";
// The URL shown in these examples is a static URL which should already
// be URL-encoded. In practice, you will likely have code
// which assembles your URL from user or web service input
// and plugs those values into its parameters.
private static String urlString = "YOUR_URL_TO_SIGN";
// This variable stores the binary key, which is computed from the string (Base64) key
private static byte[] key;
public static void main(String[] args) throws IOException,
InvalidKeyException, NoSuchAlgorithmException, URISyntaxException {
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String inputUrl, inputKey = null;
// For testing purposes, allow user input for the URL.
// If no input is entered, use the static URL defined above.
System.out.println("Enter the URL (must be URL-encoded) to sign: ");
inputUrl = input.readLine();
if (inputUrl.equals("")) {
inputUrl = urlString;
}
// Convert the string to a URL so we can parse it
URL url = new URL(inputUrl);
// For testing purposes, allow user input for the private key.
// If no input is entered, use the static key defined above.
System.out.println("Enter the Private key to sign the URL: ");
inputKey = input.readLine();
if (inputKey.equals("")) {
inputKey = keyString;
}
UrlSigner signer = new UrlSigner(inputKey);
String request = signer.signRequest(url.getPath(),url.getQuery());
System.out.println("Signed URL :" + url.getProtocol() + "://" + url.getHost() + request);
}
public UrlSigner(String keyString) throws IOException {
// Convert the key from 'web safe' base 64 to binary
keyString = keyString.replace('-', '+');
keyString = keyString.replace('_', '/');
System.out.println("Key: " + keyString);
this.key = Base64.decode(keyString);
}
public String signRequest(String path, String query) throws NoSuchAlgorithmException,
InvalidKeyException, UnsupportedEncodingException, URISyntaxException {
// Retrieve the proper URL components to sign
String resource = path + '?' + query;
// Get an HMAC-SHA1 signing key from the raw key bytes
SecretKeySpec sha1Key = new SecretKeySpec(key, "HmacSHA1");
// Get an HMAC-SHA1 Mac instance and initialize it with the HMAC-SHA1 key
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(sha1Key);
// compute the binary signature for the request
byte[] sigBytes = mac.doFinal(resource.getBytes());
// base 64 encode the binary signature
String signature = Base64.encodeBytes(sigBytes);
// convert the signature to 'web safe' base 64
signature = signature.replace('+', '-');
signature = signature.replace('/', '_');
return resource + "&signature=" + signature;
}
}
Given that you have your client Id, you should now be able to sign your request.
Next…
In Part 2, to keep things interesting and informing, we will discuss how to develop a mobile application, targeting the core features of this post. We will create some fun location-based requirements and flush out the design details.
See you next time!

3 Trackbacks