July 08, 2012

ถามหาสถานที่รอบๆ จาก foursquare

ความต้องการสำหรับ entry นี้ก็คือ เราจะโยนตำแหน่ง (latitude, longitude) ไปให้ foursquare จากนั้นจะให้มันตอบสถานที่รอบๆ ตำแหน่งนั้นกลับมาให้เรา
หลักๆ แล้วเราสามารถหาสถานที่รอบๆ จุดได้ 2 วิธี คือ
  1. ต้อง login เข้าใช้งาน foursquare ก่อนถึงจะขอสถานที่ได้ แบบนี้ต้องพึ่ง access token ที่จะได้มาหลังจาก login
  2. ไม่ต้อง login ก็สามารถขอสถานที่ได้
โดยความละเอียดของข้อมูลก็จะแต่งต่างกันไป
เริ่มจากแบบที่ต้อง login เข้าใช้งานก่อน

การที่เราจะมีสิทธิ์ในการบอกให้ foursquare ช่วยหาสถานที่ให้เราได้นั้น เราจำเป็นต้องมีสิ่งที่เรียกว่า Access Token ก่อน แต่ก่อนอื่นเราต้องลงทะเบียนโดยการเข้าไปกดปุ่ม Register a new Consumer เพื่อที่เราจะได้เป็น client ที่ foursquare รู้จักก่อน

หลังจากเราลงทะเบียนเสร็จแล้ว เราจะได้สิ่งที่เรียกว่า Client ID ติดไม้ติดมือกลับมา เท่านี้เราก็พร้อมสำหรับการขอ access token จาก foursquare แล้ว

วิธีในการขอ access token เราจะใช้ UIWebView ช่วย ดังต่อไปนี้

NSString *authenticateURLString = [NSString stringWithFormat:@"https://foursquare.com/oauth2/authenticate?client_id=%@&response_type=token&redirect_uri=%@"
                                       CLIENT_ID, CALLBACK_URL];

NSURL *url = [NSURL URLWithString:authenticateURLString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

[_webView loadRequest:request];

โดยที่ CLIENT_ID และ CALLBACK_URL เราจะได้มาตอนที่ register a new customer เสร็จแล้วดังที่ได้กล่าวไป

เมื่อ UIWebView โหลด request นี้เสร็จแล้ว เค้าก็จะให้เรา login เข้าใช้ foursquare เมื่อเสร็จแล้ว foursquare ก็จะพยายาม redirect ไปยัง CALLBACK_URL ที่เราแนบไปตอนขอ access token โดย URL ที่มันจะพยายาม redirect ไปจะแนบ access token ติดมาด้วย และเดี๋ยวเราก็จะใช้ access token ตัวนี้แหละ แนบติดไปกับตอนที่เราขอให้ foursquare ช่วยหาสถานที่ให้ :D

ซึ่ง flow การ redirect/reload ต่างๆ ให้ observe ได้ที่ delegate method ต่างๆ ของ UIWebView ได้ตามปกติ

ส่วนวิธีการแงะเอา access token ก็ทำได้แล้วแต่ความถนัดประมาณนี้

NSString *URLString = [[_webView.request URL] absoluteString];

if([URLString rangeOfString: @"access_token="].location != NSNotFound){
    NSString *accessToken = [[URLString componentsSeparatedByString: @"="] lastObject];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject: accessToken forKey: @"access_token"];
    [defaults synchronize];
}


หลังจากเราได้ access token มาแล้ว เราก็ได้สิทธิ์ที่จะขอให้ foursquare ทำอะไรๆ ต่างๆ เกี่ยวกับ user ที่ login ไป ยกตัวอย่างเช่นการหาสถานที่รอบๆ latitude, longitude ที่เราส่งไปให้แล้ว โดยใช้ API Explorer ดังนี้


NSURL *url = [NSURL URLWithString: [NSString stringWithFormat: @"https://api.foursquare.com/v2/venues/explore?ll=13.723814,100.549396&oauth_token=%@", access_token]];


__autoreleasing NSError *error;
NSString *string = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error: &error];
NSLog(@"response json = %@", string);


ถ้าเราลองพิจารณาดูจากสิ่งที่ได้กลับมา เราจะพบว่ามีข้อมูลมาให้ค่อนข้างครบครันเลยทีเดียว ทั้ง url ของรูปต่างๆ ,Comment และ Tips

แล้วหากเราต้องการหาสถานที่รอบๆ โดยไม่ต้อง Login เข้าใช้งาน foursquare ล่ะ จะทำอย่างไร? นี่คือแบบที่สองที่ว่า ที่จะทำให้เราไม่ต้อง login ก็สามารถเข้าไปขุดคุ้ยฐานข้อมูลเพื่อหาสถานที่ต่างๆ ได้

สำหรับ foursquare เค้าก็ใจดีมี API ที่ให้เราสามารถเข้าไปค้นฐานข้อมูลของเค้าโดยที่เราไม่จำเป็นต้อง login เข้าใช้งานก็ได้ สิ่งที่ foursquare เตรียมไว้ให้ใช้ (และเราจะใช้มัน) เรียกว่า Venues Platform นั่นเอง โดยที่ API หลักๆ ที่เค้าจัดเตรียมไว้ให้ก็เช่น search, tips, photos, check-in counts, here now (รายละเอียดก็อ่านได้ตาม link ที่ให้ไปเองนะ ;) ) โดยเค้าบอกไว้ว่าจำกัด request ไว้ที่ 5,000 ครั้งต่อ 1 ชั่วโมง ถ้าหากอยากได้เยอะกว่านี้ก็ให้ติดต่อเข้าไปเองเป็นกรณีต่างหาก

สำหรับ API ที่เราจะใช้ก็คือ search โดยที่เราสามารถส่ง https GET request ไปได้ตรงๆ แบบนี้เลย


NSString *string = [NSString stringWithFormat: @"https://api.foursquare.com/v2/venues/search?ll=13.723814,100.549396&limit=10&radius=2000&client_id=%@&client_secret=%@",
                        CLIENT_ID, CLIENT_SECRET];


NSURL *url = [NSURL URLWithString: string];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL: url];
[request startSynchronous];
NSLog(@"response = %@", request.responseString);


จากตัวอย่างผมใช้ ASIHttpRequest ช่วยในการส่ง https โดยสิ่งจำเป็นที่ต้องส่งไปก็คือ CLIENT_ID และ CLIENT_SECRET ที่ได้มาตอน create a consumer โดยพารามิเตอร์อื่นๆ ที่จะส่งไปด้วยได้ อ่านได้จากที่นี่

อ่านต่อ