Permalink
Browse files

Add location data and display saved data as json

  • Loading branch information...
1 parent 0002885 commit ac1360e42f6c7dbdab098e51eaef5fd2a051f0a6 @afh afh committed Apr 21, 2011
Showing with 190 additions and 21 deletions.
  1. +3 −0 .gitmodules
  2. +78 −0 OnTheSpot.xcodeproj/project.pbxproj
  3. +5 −0 OnTheSpot/RootViewController.h
  4. +91 −21 OnTheSpot/RootViewController.m
  5. +12 −0 README.textile
  6. +1 −0 Vendor/TouchJSON
View
@@ -0,0 +1,3 @@
+[submodule "Vendor/TouchJSON"]
+ path = Vendor/TouchJSON
+ url = https://github.com/TouchCode/TouchJSON.git
@@ -21,8 +21,27 @@
BCBD6725135D8E4D00B25825 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = BCBD6723135D8E4D00B25825 /* Default.png */; };
BCBD6726135D8E4D00B25825 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = BCBD6724135D8E4D00B25825 /* Default@2x.png */; };
BCBD6728135D94C200B25825 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCBD6727135D94C200B25825 /* CoreMotion.framework */; };
+ BCC6E840135DE2EC00BBA835 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BCC6E83F135DE2EC00BBA835 /* CoreLocation.framework */; };
+ BCC6E87C1360337C00BBA835 /* libTouchJSON.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BCC6E87B1360337C00BBA835 /* libTouchJSON.a */; };
/* End PBXBuildFile section */
+/* Begin PBXContainerItemProxy section */
+ BCC6E8771360336800BBA835 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = BCC6E8701360336800BBA835 /* TouchJSON-iOS.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 37A8C0F312B720A8009953BD;
+ remoteInfo = TouchJSON;
+ };
+ BCC6E8791360337500BBA835 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = BCC6E8701360336800BBA835 /* TouchJSON-iOS.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC07D0554694100DB518D;
+ remoteInfo = TouchJSON;
+ };
+/* End PBXContainerItemProxy section */
+
/* Begin PBXFileReference section */
BC2F6354135DDF0600C63709 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = "<group>"; };
BC2F6355135DDF0600C63709 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = "<group>"; };
@@ -44,13 +63,19 @@
BCBD6723135D8E4D00B25825 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
BCBD6724135D8E4D00B25825 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
BCBD6727135D94C200B25825 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
+ BCC6E83F135DE2EC00BBA835 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
+ BCC6E8701360336800BBA835 /* TouchJSON-iOS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "TouchJSON-iOS.xcodeproj"; path = "Vendor/TouchJSON/Support/TouchJSON-iOS.xcodeproj"; sourceTree = "<group>"; };
+ BCC6E87B1360337C00BBA835 /* libTouchJSON.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libTouchJSON.a; sourceTree = SOURCE_ROOT; };
+ BCC6E87E136034BA00BBA835 /* CJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CJSONSerializer.h; path = ../Vendor/TouchJSON/Source/JSON/CJSONSerializer.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
BCB64287135D7F5000DA6256 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ BCC6E87C1360337C00BBA835 /* libTouchJSON.a in Frameworks */,
+ BCC6E840135DE2EC00BBA835 /* CoreLocation.framework in Frameworks */,
BCBD6728135D94C200B25825 /* CoreMotion.framework in Frameworks */,
BCB6428F135D7F5000DA6256 /* UIKit.framework in Frameworks */,
BCB64291135D7F5000DA6256 /* Foundation.framework in Frameworks */,
@@ -64,9 +89,11 @@
BCB6427F135D7F5000DA6256 = {
isa = PBXGroup;
children = (
+ BCC6E8701360336800BBA835 /* TouchJSON-iOS.xcodeproj */,
BCBD6723135D8E4D00B25825 /* Default.png */,
BCBD6724135D8E4D00B25825 /* Default@2x.png */,
BCB64294135D7F5000DA6256 /* OnTheSpot */,
+ BCC6E87D1360338E00BBA835 /* LIbraries */,
BCB6428D135D7F5000DA6256 /* Frameworks */,
BCB6428B135D7F5000DA6256 /* Products */,
);
@@ -83,6 +110,7 @@
BCB6428D135D7F5000DA6256 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ BCC6E83F135DE2EC00BBA835 /* CoreLocation.framework */,
BCBD6727135D94C200B25825 /* CoreMotion.framework */,
BCB6428E135D7F5000DA6256 /* UIKit.framework */,
BCB64290135D7F5000DA6256 /* Foundation.framework */,
@@ -94,6 +122,7 @@
BCB64294135D7F5000DA6256 /* OnTheSpot */ = {
isa = PBXGroup;
children = (
+ BCC6E87E136034BA00BBA835 /* CJSONSerializer.h */,
BCB6429D135D7F5000DA6256 /* OnTheSpotAppDelegate.h */,
BCB6429E135D7F5000DA6256 /* OnTheSpotAppDelegate.m */,
BCB642A0135D7F5000DA6256 /* MainWindow.xib */,
@@ -119,6 +148,22 @@
name = "Supporting Files";
sourceTree = "<group>";
};
+ BCC6E8711360336800BBA835 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ BCC6E8781360336800BBA835 /* libTouchJSON.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ BCC6E87D1360338E00BBA835 /* LIbraries */ = {
+ isa = PBXGroup;
+ children = (
+ BCC6E87B1360337C00BBA835 /* libTouchJSON.a */,
+ );
+ name = LIbraries;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -133,6 +178,7 @@
buildRules = (
);
dependencies = (
+ BCC6E87A1360337500BBA835 /* PBXTargetDependency */,
);
name = OnTheSpot;
productName = OnTheSpot;
@@ -157,13 +203,29 @@
mainGroup = BCB6427F135D7F5000DA6256;
productRefGroup = BCB6428B135D7F5000DA6256 /* Products */;
projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = BCC6E8711360336800BBA835 /* Products */;
+ ProjectRef = BCC6E8701360336800BBA835 /* TouchJSON-iOS.xcodeproj */;
+ },
+ );
projectRoot = "";
targets = (
BCB64289135D7F5000DA6256 /* OnTheSpot */,
);
};
/* End PBXProject section */
+/* Begin PBXReferenceProxy section */
+ BCC6E8781360336800BBA835 /* libTouchJSON.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libTouchJSON.a;
+ remoteRef = BCC6E8771360336800BBA835 /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
/* Begin PBXResourcesBuildPhase section */
BCB64288135D7F5000DA6256 /* Resources */ = {
isa = PBXResourcesBuildPhase;
@@ -194,6 +256,14 @@
};
/* End PBXSourcesBuildPhase section */
+/* Begin PBXTargetDependency section */
+ BCC6E87A1360337500BBA835 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = TouchJSON;
+ targetProxy = BCC6E8791360337500BBA835 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
/* Begin PBXVariantGroup section */
BCB64297135D7F5000DA6256 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
@@ -263,6 +333,10 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "OnTheSpot/OnTheSpot-Prefix.pch";
INFOPLIST_FILE = "OnTheSpot/OnTheSpot-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)\"",
+ );
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = 1;
WRAPPER_EXTENSION = app;
@@ -277,6 +351,10 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "OnTheSpot/OnTheSpot-Prefix.pch";
INFOPLIST_FILE = "OnTheSpot/OnTheSpot-Info.plist";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(SRCROOT)\"",
+ );
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = 1;
VALIDATE_PRODUCT = YES;
@@ -8,16 +8,21 @@
#import <UIKit/UIKit.h>
#import <CoreMotion/CMMotionManager.h>
+#import <CoreLocation/CoreLocation.h>
@interface RootViewController : UITableViewController
< UINavigationControllerDelegate
, UIImagePickerControllerDelegate
+, CLLocationManagerDelegate
> {
@private
NSMutableArray* _images;
NSMutableArray* _motionSamples;
CMMotionManager* _motionManager;
+ CLLocationManager* _locationManager;
+ NSMutableArray* _locationSamples;
+ NSMutableArray* _headingSamples;
NSTimer* _sampleTimer;
}
@@ -8,6 +8,7 @@
#import "RootViewController.h"
#import "DetailViewController.h"
+#import "CJSONSerializer.h"
@interface RootViewController()
@property (nonatomic, retain) NSMutableArray* images;
@@ -28,22 +29,11 @@ - (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self = [super initWithCoder:aDecoder])) {
_motionManager = [CMMotionManager new];
- }
- return self;
-}
-
-- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
-{
- if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
- _motionManager = [CMMotionManager new];
- }
- return self;
-}
-
-- (id)initWithStyle:(UITableViewStyle)style
-{
- if ((self = [super initWithStyle:style])) {
- _motionManager = [CMMotionManager new];
+ _locationManager = [CLLocationManager new];
+ _locationManager.delegate = self;
+ _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
+ _locationManager.distanceFilter = kCLDistanceFilterNone;
+ _locationManager.purpose = NSLocalizedString(@"Location services are used to attach the location of where a photo was taken.", nil);
}
return self;
}
@@ -161,7 +151,15 @@ - (void)tableView:(UITableView *)tableView
NSDictionary* jsonData = [_images objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController.imageView.image = [jsonData valueForKey:@"imageData"];
- detailViewController.textView.text = [jsonData description];
+ NSError* error = NULL;
+ NSData* theJSON = [[CJSONSerializer serializer] serializeDictionary:jsonData error:&error];
+ if (error != NULL) {
+ NSLog(@"Error while serializing %@", jsonData);
+ detailViewController.textView.text = [jsonData description];
+ }
+ else {
+ detailViewController.textView.text = [[NSString alloc] initWithData:theJSON encoding:NSUTF8StringEncoding];
+ }
[detailViewController release];
}
@@ -184,14 +182,14 @@ - (void)viewDidUnload
- (void)dealloc
{
[_motionManager release];
+ [_locationManager release];
[super dealloc];
}
- (IBAction)takePicture
{
// start background motion sampling
- [self performSelector
- :@selector(startMotionSampling) withObject:nil];
+ [self startMotionSampling];
// present camera ui
UIImagePickerController *vc = [[UIImagePickerController alloc] init];
@@ -216,6 +214,36 @@ - (void)imagePickerController:(UIImagePickerController *)picker
[self storeImage:image withMetaData:metaData];
}
+#pragma mark -
+#pragma mark CLLocationManagerDelegate Methods
+- (void)locationManager:(CLLocationManager *)manager
+ didFailWithError:(NSError *)error
+{
+ NSLog(@"CLLocationManager:didFailWithError: %@", error);
+}
+
+- (void)locationManager:(CLLocationManager *)manager
+ didUpdateToLocation:(CLLocation *)newLocation
+ fromLocation:(CLLocation *)oldLocation
+{
+ NSMutableDictionary* sample = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSDate date], @"timestamp"
+ , newLocation, @"location"
+ , nil];
+ [_locationSamples addObject:sample];
+
+}
+
+- (void)locationManager:(CLLocationManager *)manager
+ didUpdateHeading:(CLHeading *)newHeading
+{
+ NSMutableDictionary* sample = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ [NSDate date], @"timestamp"
+ , newHeading, @"heading"
+ , nil];
+ [_headingSamples addObject:sample];
+}
+
- (void)storeImage:(UIImage*)anImage withMetaData:(NSDictionary*)metaData
{
NSDictionary* exifData = [metaData valueForKey:@"{Exif}"];
@@ -242,10 +270,30 @@ - (void)storeImage:(UIImage*)anImage withMetaData:(NSDictionary*)metaData
}
NSAssert(motionData != nil, @"Missing motion sample for image take at %@", metaData);
+ NSDictionary* locationData = nil;
+ for (NSDictionary* sample in _locationSamples) {
+ NSDate* sampleTimestamp = [sample valueForKey:@"timestamp"];
+ if ([dateTimeDigitized timeIntervalSinceDate:sampleTimestamp] <= 0.0) {
+ locationData = sample;
+ break;
+ }
+ }
+
+ NSDictionary* headingData = nil;
+ for (NSDictionary* sample in _headingSamples) {
+ NSDate* sampleTimestamp = [sample valueForKey:@"timestamp"];
+ if ([dateTimeDigitized timeIntervalSinceDate:sampleTimestamp] <= 0.0) {
+ headingData = sample;
+ break;
+ }
+ }
+
NSMutableDictionary* jsonData = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- metaData, @"mediaMetaData"
+ anImage, @"imageData" // will be stored as an attachment to the document in CouchDB
+ , metaData, @"mediaMetaData"
, motionData, @"motionData"
- , anImage, @"imageData" // will be stored as an attachment to the document in CouchDB
+ , locationData, @"locationData"
+ , headingData, @"headingData"
, nil];
[_images addObject:jsonData];
[self.tableView reloadData];
@@ -262,6 +310,18 @@ - (void)startMotionSampling
else {
[_motionSamples removeAllObjects];
}
+ if (nil == _locationSamples) {
+ _locationSamples = [[NSMutableArray alloc] init];
+ }
+ else {
+ [_locationSamples removeAllObjects];
+ }
+ if (nil == _headingSamples) {
+ _headingSamples = [[NSMutableArray alloc] init];
+ }
+ else {
+ [_headingSamples removeAllObjects];
+ }
// start motion sensor updates
if (!_motionManager.gyroActive && _motionManager.gyroAvailable) {
@@ -277,6 +337,13 @@ - (void)startMotionSampling
[_motionManager startAccelerometerUpdates];
}
+ if ([CLLocationManager locationServicesEnabled]) {
+ [_locationManager startUpdatingLocation];
+ }
+ if ([CLLocationManager headingAvailable]) {
+ [_locationManager startUpdatingHeading];
+ }
+
self.sampleTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(takeMotionSample:)
@@ -298,6 +365,9 @@ - (void)stopMotionSampling
if (_motionManager.accelerometerActive && _motionManager.accelerometerAvailable) {
[_motionManager stopAccelerometerUpdates];
}
+
+ [_locationManager startUpdatingLocation];
+ [_locationManager startUpdatingHeading];
}
- (void)takeMotionSample:(NSTimer*)aTimer
View
@@ -0,0 +1,12 @@
+h1. On The Spot
+
+A simple iOS application that takes a pictures and stores additional information, like media meta data, location data, motion sensor data along with the image in a CouchDB.
+
+h2. Requirements
+
+"TouchJSON":http://github.com/touchCode/TouchJSON
+
+Run the following commands to initialize the workspace
+
+ % git submodule init
+ % git submodule update
Submodule TouchJSON added at 2abba3

0 comments on commit ac1360e

Please sign in to comment.