iOS(iphone)アプリで位置情報を取得、それをrailsアプリに送信してDBに登録するようにしてみます。
なおiOSについてはまだまだ勉強不足のため、「
まるごと学ぶiPhoneアプリ制作教室
」内に記載してあったコードを参考にしています。
またrailsアプリ内には位置情報の取得まで作っておきますが、iOS部分では省きます。
まずはiOSアプリの方。
ViewController.m
- #import "ViewController.h"
- #import "Location.h"
- #import "JSON.h"
-
- @implementation ViewController
- @synthesize codeTextField;
-
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
-
- }
-
- #pragma mark - View lifecycle
-
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
- }
-
- - (void)viewDidUnload
- {
- [self setCodeTextField:nil];
- [super viewDidUnload];
-
-
- }
-
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
- }
-
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
- }
-
- - (void)viewWillDisappear:(BOOL)animated
- {
- [super viewWillDisappear:animated];
- }
-
- - (void)viewDidDisappear:(BOOL)animated
- {
- [super viewDidDisappear:animated];
- }
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
-
- return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
- }
-
- - (NSString *)getCurrentDate {
- NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
- NSString *dateFormat = @"yyyy/MM/dd-mm:ss:SSS";
- [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"JST"]];
- [dateFormatter setDateFormat:dateFormat];
- NSString *date = [dateFormatter stringFromDate:[NSDate date]];
- return date;
- }
-
- - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
-
-
- Location *myLocation = [[[Location alloc] init] autorelease];
- myLocation.latitude = [NSString stringWithFormat:@"%f", newLocation.coordinate.latitude];
- myLocation.longitude = [NSString stringWithFormat:@"%f", newLocation.coordinate.longitude];
- myLocation.time = [self getCurrentDate];
- myLocation.identificationCode = [codeTextField text];
-
- NSDictionary *locationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
- myLocation.latitude, @"latitude",
- myLocation.longitude, @"longitude",
- myLocation.time, @"time",
- myLocation.identificationCode, @"identificationCode",
- nil];
- NSString* jsonString = [locationDictionary JSONRepresentation];
- NSLog(@"JSON: %@", jsonString);
-
- NSURL *serviceURL = [NSURL URLWithString:@"http://0.0.0.0:3000/location.json"];
- NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:serviceURL];
- [req setHTTPMethod:@"POST"];
- [req addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
- [req setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
-
- NSURLResponse *resp= nil;
- NSError *error= nil;
- NSData *result = [NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:&error];
-
- if (error) {
- NSLog(@"error!");
- } else {
- NSLog(@"Result:%@", result);
- }
-
- }
- - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
- }
- - (IBAction)logStartButton:(id)sender {
- if (locationManager == nil) {
- locationManager = [[CLLocationManager alloc] init];
- }
- locationManager.delegate = self;
- [locationManager startUpdatingLocation];
- }
- - (void)dealloc {
- [codeTextField release];
- [super dealloc];
- }
- @end
#import "ViewController.h"
#import "Location.h"
#import "JSON.h"
@implementation ViewController
@synthesize codeTextField;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setCodeTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (NSString *)getCurrentDate {
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
NSString *dateFormat = @"yyyy/MM/dd-mm:ss:SSS";
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"JST"]];
[dateFormatter setDateFormat:dateFormat];
NSString *date = [dateFormatter stringFromDate:[NSDate date]];
return date;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
Location *myLocation = [[[Location alloc] init] autorelease];
myLocation.latitude = [NSString stringWithFormat:@"%f", newLocation.coordinate.latitude];
myLocation.longitude = [NSString stringWithFormat:@"%f", newLocation.coordinate.longitude];
myLocation.time = [self getCurrentDate];
myLocation.identificationCode = [codeTextField text];
NSDictionary *locationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
myLocation.latitude, @"latitude",
myLocation.longitude, @"longitude",
myLocation.time, @"time",
myLocation.identificationCode, @"identificationCode",
nil];
NSString* jsonString = [locationDictionary JSONRepresentation];
NSLog(@"JSON: %@", jsonString);
NSURL *serviceURL = [NSURL URLWithString:@"http://0.0.0.0:3000/location.json"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:serviceURL];
[req setHTTPMethod:@"POST"];
[req addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[req setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLResponse *resp= nil;
NSError *error= nil;
NSData *result = [NSURLConnection sendSynchronousRequest:req returningResponse:&resp error:&error];
if (error) {
NSLog(@"error!");
} else {
NSLog(@"Result:%@", result);
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
}
- (IBAction)logStartButton:(id)sender {
if (locationManager == nil) {
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
[locationManager startUpdatingLocation];
}
- (void)dealloc {
[codeTextField release];
[super dealloc];
}
@end
ViewController.h
- #import <UIKit/UIKit.h>
- #import "CoreLocation/CoreLocation.h"
-
- @interface ViewController : UIViewController <CLLocationManagerDelegate> {
- @private
- UITextField *codeTextField;
- UIButton *logStartButton;
- CLLocationManager *locationManager;
- }
- @property (retain, nonatomic) IBOutlet UITextField *codeTextField;
- - (IBAction)logStartButton:(id)sender;
-
- @end
#import <UIKit/UIKit.h>
#import "CoreLocation/CoreLocation.h"
@interface ViewController : UIViewController <CLLocationManagerDelegate> {
@private
UITextField *codeTextField;
UIButton *logStartButton;
CLLocationManager *locationManager;
}
@property (retain, nonatomic) IBOutlet UITextField *codeTextField;
- (IBAction)logStartButton:(id)sender;
@end
Location.h
- #import <Foundation/Foundation.h>
-
- @interface Location : NSObject {
- NSString *latitude;
- NSString *longitude;
- NSString *time;
- NSString *identificationCode;
- }
- @property (nonatomic, assign) NSString *latitude;
- @property (nonatomic, assign) NSString *longitude;
- @property (nonatomic, assign) NSString *time;
- @property (nonatomic, assign) NSString *identificationCode;
-
- @end
#import <Foundation/Foundation.h>
@interface Location : NSObject {
NSString *latitude;//緯度
NSString *longitude;//経度
NSString *time;//時間
NSString *identificationCode;//自分を特定するためのIDコード
}
@property (nonatomic, assign) NSString *latitude;
@property (nonatomic, assign) NSString *longitude;
@property (nonatomic, assign) NSString *time;
@property (nonatomic, assign) NSString *identificationCode;
@end
- #import "Location.h"
-
- @implementation Location
- @synthesize latitude;
- @synthesize longitude;
- @synthesize time;
- @synthesize identificationCode;
-
- @end
#import "Location.h"
@implementation Location
@synthesize latitude;
@synthesize longitude;
@synthesize time;
@synthesize identificationCode;
@end
Location.m
- #import "Location.h"
-
- @implementation Location
- @synthesize latitude;
- @synthesize longitude;
- @synthesize time;
- @synthesize identificationCode;
-
- @end
#import "Location.h"
@implementation Location
@synthesize latitude;
@synthesize longitude;
@synthesize time;
@synthesize identificationCode;
@end
CoreLocationライブラリは別途入れてください。
また
ここから「JSON v2.3.2 (iOS)」をダウンロードして、その中からClassesフォルダを同じプロジェクトファイル内にコピーしておいてください。
なおserviceURL = [NSURL URLWithString:@"http://0.0.0.0:3000/location.json"]のドメイン部分は自分なりに。
xibも適当にボタンとテキストフィールドを。名称は、それぞれ「logStartButton」「codeTextField」で。
わからないときは、「
まるごと学ぶiPhoneアプリ制作教室
」を参考にしてください。
サンプルコードが
ここにあったりします。
次にrailsの方。
ApiController
- class ApiController < ApplicationController
-
- def post
- location = Location.new(params[:api])
- respond_to do |format|
- if location.save
- format.json { head :ok }
- else
- format.json { render json: location.errors, status: :unprocessable_entity }
- end
- end
- end
-
- def get
- @location = Location.where(:identificationCode => params[:identificationCode]).limit(5)
-
- respond_to do |format|
- format.json { render json: @location }
- end
- end
-
- end
class ApiController < ApplicationController
def post
location = Location.new(params[:api])
respond_to do |format|
if location.save
format.json { head :ok }
else
format.json { render json: location.errors, status: :unprocessable_entity }
end
end
end
def get
@location = Location.where(:identificationCode => params[:identificationCode]).limit(5)
respond_to do |format|
format.json { render json: @location }
end
end
end
ルーティングとして以下を追加。
- post 'location(.:format)' => 'api#post'
- get 'location(.:format)' => 'api#get'
post 'location(.:format)' => 'api#post'
get 'location(.:format)' => 'api#get'
データベースに以下のカラムを作る
「latitude」
「longitude」
「time」
「identificationCode」
で、マイグレして起動して、iPhoneアプリを起動し、ボタンを押せば、1秒ごとにrailsのDBに位置情報とID、時間が登録されていくはずです。
ポイントは、jsonデータをpostメソッドで送信するとそれぞれのparams[:項目名]で取得できること。
それができれば簡単ではないかと。
今回簡易的にするため外のpostメソッドをそのまま受け入れましたが、セキュリティ的には問題あるので、実用にはもうちょい工夫が必要そうです。