Monday, July 4, 2011

Working with Google Places API

In this post I will demonstrate how to work with google places API. Also i would request you to go through this link before continuing with this tutorial as their is a bug with the places api as you cannot find some of the places from india.
What is Google Places API:
The Google Places API is a service that returns information about Places — defined within this API as establishments, geographic locations, or prominent points of interest.
How to work with google api: The google api works some what like this you supply in the coordinates of a specific place and it will give you the output either in xml or json format, but in order to get that output you must have the API key with you and that key is provided by google, so how to get that API key well if you follow the instructions given in this link then its quite easy.
Design Phase: The flow of the entire demo is like this
a.     I will be displaying the entire bank list by supplying the coordinates of the Los Angeles and will be displaying the entire bank list in the table view. I will be parsing the places api xml output for this by using GData Parser (If you want to know how does the Gdata parser works then please refer to one of my previous blogs post that I wrote on GData).
b.  The Places Api XML output will also have the latitude and longitude for the banks so I will be making the use of the MapKit Framework to display the location of those banks with Pin Annotation.
c.  I will be using the Navigation Controller to display the table view containing the bank list and then when the user selects an appropriate bank name then with the help of the navigation controller he/she will be traversed to the next view, which would be our map view.
d. You can not only search for banks with the help of google places api but also lots of other stuff as well here’s a link to the items that you can search with the help of the places api. 

here’s a view at the final output


Step 1: Open Xcode and create a windows based application and give it a name GooglePlacesDemo or any name of your choice will also do, Add the UITableViewController subclass file to the project with the name PlacesTableViewController, that will result in adding of two new files into your project that would be PlacesTableViewController.h and PlacesTableViewController.m. Now here’s what we are going to do next we are going to get our places API key by referring the steps given in the google link.
Step 2: By now I feel you must be having your API key that would be required by you to get the data from the places API. Once this is done the next step is to get the GData parser which you can get from here and if you are new to GDataXML Parser well here’s a tutorial that I wrote earlier, please perform the setting part only for the GData parser.
Once this is done I would request you to add a new file of the UIViewController subclass and this file would be for the map view, so add a new file and give it the name MapViewController, so now their will be two more new files into your project (MapViewController.h and MapViewController.m). Guys I want you to follow my annotation post and be ready with the annotation coding part because we will be needing it.
Step 3: The structure of the XML file that we will be parsing would look some what like this so please have a close look at the xml file

The logic to parse the names and the destination of the banks are given below and this method is used inside the PlacesTableViewController.m file and make sure that you call this method inside the init method of the PlacesTableViewController

-(void)ParseXML_of_Google_PlacesAPI

{

    NSURL *googlePlacesURL = [NSURL URLWithString:PlacesURL];

    NSData *xmlData = [NSData dataWithContentsOfURL:googlePlacesURL];

    xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:nil];

    NSArray *arr = [xmlDocument.rootElement elementsForName:@"result"];

    for(GDataXMLElement *e in arr )

    {

        [placesOutputArray addObject:e];

    }

    
}
Code Explanation: I don’t think that I should explain the above code in detail because they are self explanatory, you tell the GDataXMLDocument whats the structure of your xml file is and then apply a for loop for adding the entire element of the XML file inside a mutable array. Now what you can do is use this mutable array to display the name of the banks present in the XML file in your table and you do that like this. The PlacesURL is a macro that i am using, and it contains the entire link to the API including the coordinates and the place that you want to get like banks, atms, schools etc here's the view to that
#define PlacesURL @"https://maps.googleapis.com/maps/api/place/search/xml?location=34.0522222,-118.2427778&radius=500&types=bank&sensor=false&key=TheAPIKey_You_Got
 Given below is the code that will display the xml data from the mutable array to the table, so inside the cellForRowAtIndexPath method of the table add this piece of code.


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }
   
    // Configure the cell...
    cell.textLabel.text = [[[placesOutputArray objectAtIndex:indexPath.row] childAtIndex:0] stringValue];
    cell.detailTextLabel.text = [[[placesOutputArray objectAtIndex:indexPath.row] childAtIndex:1] stringValue];


    return cell;
}


Similarly you may use the above code if you are parsing the XML file for atms, schools etc and for that just change the text from the PlaceURL macro from banks to atms or schools or what ever place you want and all you have to do is change the text from the PlacesURL macro from bank to school.

Step 4: I would request you to take your time and read the above code do your part of the research and then start reading the step 4 as it is involved with the map part.
Now half of the application has been completed, now the only thing remaining is to show the annotation part inside the map (if you don’t know how to add annotation then please read this post), select the NSObject class that you must have used to display the annotation in the map and create your own init method because we will get the latitude, longitude and the name of the bank from the PlacesTableViewController file.
This is how the init method will look like in the .h file

-(id)initWithName:(NSString*)_placeName andCoordinates:(CLLocationCoordinate2D)_coordinates; 

And this is how it will be implemented in the .m file
-(id)initWithName:(NSString*)_placeName andCoordinates:(CLLocationCoordinate2D)_coordinates
{

    pinTitle = _placeName;
    _theCords = _coordinates;

    return self;
}

The pinTitle is a object of the NSString class declared in the .h file of the NSObject class that you will be using to display the annotation and the _theCords is the variable of the structure of the CLLocationCoordinate2D.


The code for adding the annotation looks like this in the NSObject class for the annotation
-(CLLocationCoordinate2D)coordinate
{

   CLLocationCoordinate2D cords = {_theCords.latitude,_theCords.longitude};
    return cords;

}



Step 5:  yes i forgot to mention you have to make your own init method inside the MapViewController class here's the view to that and why are we doing this you will come to know this when we proceed with the tutorial
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil bankName:(NSString*)_name andCoordinates:(CLLocationCoordinate2D)bankcords;


Please select the PlacesTableViewController.m file and please traverse through tableView:didselect row method and modify this code as per your project

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

    //storing the title inside the str variable

    NSString *str = [[[placesOutputArray objectAtIndex:indexPath.row] childAtIndex:0] stringValue];

   

    //parsing for latitude

   

    double lat = [[[[[[[[placesOutputArray objectAtIndex:indexPath.row]elementsForName:@"geometry"] objectAtIndex:0] elementsForName:@"location"] objectAtIndex:0] childAtIndex:0]stringValue]doubleValue];

   

    //parsing for longitude

    double lng = [[[[[[[[placesOutputArray objectAtIndex:indexPath.row]elementsForName:@"geometry"] objectAtIndex:0] elementsForName:@"location"] objectAtIndex:0] childAtIndex:1] stringValue] doubleValue];

   

    //adding the new latitude and longitude inside the CLLocationCordinate2D variable

    CLLocationCoordinate2D _cords = {lat,lng};

   

    //supplying the bank title and the bank coordinates to the MapViewController class so that it we can use them inside the MapViewController to display the annotation with the title...

    mapViewC = [[MapViewController alloc]initWithNibName:nil bundle:nil bankName:str andCoordinates:_cords];


    [self.navigationController pushViewController:mapViewC animated:YES];

   

}

  
Code Explanation:  The str is a NSString variable which contains the name of the bank, the lat and lng are double variables which contains the parsed coordinates value from the xml file and since we want to supply these values to the NSObject class then I thought of creating own init method inside the MapViewController class so that the data can flow from the PlacesTableView to the MapView and from their to the NSObject class.
Inside the MapViewController.m file here's how i make use of this data and
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil bankName:(NSString*)_name andCoordinates:(CLLocationCoordinate2D)bankcords
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        bankName = _name;
        globalCords = bankcords;
    }
    return self;
}

Code Explanation: bankName is the object of the NSString class declared in the .h file of the MapViewController and globalCords is the variable of the CLLocationCordinate2D.

Select the loadView method of the MapViewController class and add the following code.

- (void)loadView
{
    [super loadView];
    //allocating memory for the mapview
    mpView = [[MKMapView alloc]initWithFrame:self.view.bounds];
   
    //allocating memory for the NSObject class used to display the mapannotation
    mapAnnotObject = [[MyMapAnnot alloc]initWithName:bankName andCoordinates:globalCords];
   
    //showing a particular region on the map
    CLLocationCoordinate2D cord = {globalCords.latitude,globalCords.longitude};
    MKCoordinateSpan spn = {0.01,0.01};
    MKCoordinateRegion reg = {cord,spn};
    [mpView setRegion:reg];
   
    //adding the annotation on the map view
    [mpView addAnnotation:mapAnnotObject];
   
    //adding the mapview to the view
    [self.view addSubview:mpView];
   
}
 


Now select the app delegate .m file and add the placesTableViewCOntroller to the UINavigationController object and add the navigation controller object to the iPhone window

#import "GooglePlacesAPIDemoAppDelegate.h"
#import "PlacesTableViewController.h"

@implementation GooglePlacesAPIDemoAppDelegate

@synthesize window=_window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    PlacesTableViewController *obj = [[PlacesTableViewController alloc]init];

    UINavigationController *navC = [[UINavigationController alloc]initWithRootViewController:obj];
    [self.window addSubview:navC.view];
    [self.window makeKeyAndVisible];
    return YES;
}

Run the application you will get the following output
Banks of the LA




Map View
So if you even change the string from the PlacesURL macro to atm or school the above code will work fine, here's how to perform the first change inside the PlacesURL macro
#define PlacesURL @"https://maps.googleapis.com/maps/api/place/search/xml?location=34.0522222,-118.2427778&radius=500&types=school&sensor=false&key=YourAPI_Key”

Now after making the above change from banks to schools the output will be not for banks but for schools.

Schools List








You may download the source code from here.




I hope that this post helped you in learning how to use google places api, comments are always welcome, Happy iCoding and have a great Day.

28 comments:

  1. Awesome, I loved your blog!!!

    ReplyDelete
  2. This is really great. Is there any chance of you posting source code?

    ReplyDelete
  3. @Anonymous: this is something which i have also thought about and now i don't have any such ideas to get the source code available for download because i am planning to get a domain soon and make everything available their, but for now you may send me a test mail at my mail ID and i will surely provide you with the source code of this demo.

    ReplyDelete
  4. @Radix: Sir can u send me the source code omn email please.
    i want to implement google places in my application.
    thanx in advance.

    mahendrachouhan1@gmail.com

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Hi,

    By using this can i get perticular locations? Ex: banks in Bangalore. can i get all banks in bangalore ?

    ReplyDelete
    Replies
    1. @Geetha:

      can i get all fuel station location for india..
      if you find your solution so please help me..!!!

      thank you.@@@

      Delete
  7. @Geetha: Hi the places api does not return the result for places in india i have shared a link at the beginning of this post, you may go through that link, the places api works fine for the other countries, but if you are looking for an api which does this kind of stuff then in that case i would say use the foursquare API.

    ReplyDelete
  8. Hi

    Your post is really interesting and helpful. Ok we can use googleplaces api. But in my project i can get my current location coordinates and i want to show nearby buisness officess in order of nearest first. How can i do that.

    ReplyDelete
  9. @anonymous: hi hope you are doing fine,
    in the above post i have shared a link on what google places have to offer like what all things you can search, please have a look at that i hope that should solve your doubt.

    ReplyDelete
  10. This is most confusing tutorial ever. Try to give proper names to classes and call those classes with those names instead of that class or this class.

    ReplyDelete
  11. Hi, Sorry about above post. Actually your tutorial is good but if u would have explained with classes names instead of (like from NSObject class which u selected etc.) would've been better. anyhow thanks for wonderful tutorial.

    ReplyDelete
  12. @anonymous: Your welcome and i would update the above tutorial as per your need.

    ReplyDelete
  13. Hi Sir,
    I am trying to implement Google places API in my App for finding places but my App requires to search hotels in user supplied location. So the co-ordinates must be dynamically supplied. Plz can i have your code to study and any help regarding the same.

    Thanks & Regards
    Suraj Mirajkar

    ReplyDelete
  14. this is really hard to follow

    ReplyDelete
  15. Can you please email me the source please


    Thank you
    tdizzle.thomas@gmail.com

    ReplyDelete
  16. Can you also email me the source please.

    Thanks
    decarlomw@gmail.com

    ReplyDelete
  17. hi can u plz send me the source code on email add plz.

    Thanks in advance.\

    it.gulshan@gmail.com

    ReplyDelete
  18. i have tried up to three step but the url with API key that i created from google console throughs an erroe like, on safari,
    REQUEST_DENIED

    What i have to do ?

    ReplyDelete
  19. Hardik: Read the status code in the google docs that should solve your problem.

    If it dosent then in that case make sure that you copy pasted the API key properly by google.

    ReplyDelete
  20. Source code is now available for downlaod

    ReplyDelete
  21. @Radix:

    i am developing an i phone application for finding fuel location near current location of iphone for india.

    i want petrol,diesel and gas station location of india in my application but in this code it will give location of Los Angeles only and location of school,bank etc..
    how do i get this location please help us..
    thank you.!!

    ReplyDelete
    Replies
    1. @Jayraj: I have hard coded the place for los angeles if you want the device to get your location then kindly use the core location framework, which will give you your latitude and longitude.

      Here's a link to my blog on core location that might help you:
      http://iphonebyradix.blogspot.in/2011/02/core-location.html

      That's all you have to do in case of any troubles do let me know

      Delete
    2. @Radix: thank you very much for your reply.. i will check your link and try if any problem occurs then i will contact you.!!
      Thank you so much...!!@!@!

      Delete
  22. nice tutorial for newbie in iphone app development!!!

    ReplyDelete
  23. Thanks alot sir. You rock

    ReplyDelete
  24. vry thnx sir 4 ur useful info,can u plz send me d src code 4 it.thnx in advance!!!!!!
    email id:indrajaindu1234@gmail.com

    ReplyDelete