diff --git a/LifeLog/LifeLog/HomeViewController.m b/LifeLog/LifeLog/HomeViewController.m
index b98cfe7..4b7ddd1 100644
--- a/LifeLog/LifeLog/HomeViewController.m
+++ b/LifeLog/LifeLog/HomeViewController.m
@@ -235,20 +235,23 @@ static NSInteger numberTotal = 10000;
// NSLog(@"%@", activityExtra.activity.startDate);
[weakSelf.pedometer queryPedometerDataFromDate:activityExtra.activity.startDate toDate:activityExtra.endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
NSInteger numberStep = [pedometerData.numberOfSteps integerValue];
-
+ int mode = 1;
if (activityExtra.activity.cycling) {
// self.bike
weakSelf.bike += numberStep;
//NSLog(@"Step cycling");
+ mode = 3;
}
else if (activityExtra.activity.walking) {
// self.walking
weakSelf.walking += numberStep;
//NSLog(@"Step walking");
+ mode = 1;
}
else if (activityExtra.activity.running) {
weakSelf.running += numberStep;
//NSLog(@"Step running");
+ mode = 2;
}
else {
// unknown
@@ -256,6 +259,19 @@ static NSInteger numberTotal = 10000;
}
// NSLog(@"Number of step--> %ld", numberStep);
weakSelf.countComplete += 1;
+
+ // save step to server
+ if (numberStep > 0) {
+ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+ [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+ NSString *dateBegin = [dateFormatter stringFromDate:activityExtra.activity.startDate];
+ NSString *dateEnd = [dateFormatter stringFromDate:activityExtra.endDate];
+ [[ServerAPI server] requestCreateLog:mode withStep:(int)numberStep startDate:dateBegin endDate:dateEnd CompletionHandler:^(NSError *error) {
+ if (error) {
+ NSLog(@"Error: %@", error);
+ }
+ }];
+ }
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf updateStepUI];
});
diff --git a/LifeLog/LifeLog/Info.plist b/LifeLog/LifeLog/Info.plist
index f27f8b7..0b2ac8e 100644
--- a/LifeLog/LifeLog/Info.plist
+++ b/LifeLog/LifeLog/Info.plist
@@ -60,5 +60,9 @@
UIViewControllerBasedStatusBarAppearance
+ NSLocationWhenInUseUsageDescription
+ This application requires location services to work
+ NSLocationAlwaysUsageDescription
+ This application requires location services to work
diff --git a/LifeLog/LifeLog/MapViewController.m b/LifeLog/LifeLog/MapViewController.m
index ac3c418..d261ec5 100644
--- a/LifeLog/LifeLog/MapViewController.m
+++ b/LifeLog/LifeLog/MapViewController.m
@@ -7,9 +7,33 @@
//
#import "MapViewController.h"
+#import
+#import
+#import
+#import "NSDate+helper.h"
+#import "Utilities.h"
-@interface MapViewController ()
+@interface MapViewController ()
+{
+ CLGeocoder *geocoder;
+ CLPlacemark *placemark;
+ CLLocation *previousLocation;
+}
+@property (weak, nonatomic) IBOutlet MKMapView *mapView;
+@property (weak, nonatomic) IBOutlet UILabel *lblTime;
+@property (weak, nonatomic) IBOutlet UISlider *slider;
+
+@property (nonatomic, weak) IBOutlet UILabel *lblValueStep;
+@property (nonatomic, weak) IBOutlet UILabel *lblUnitStep;
+@property (strong, nonatomic) CLLocationManager *locationManager;
+
+@property (nonatomic, strong) CMPedometer *pedometer;
+@property (nonatomic, strong) CMMotionActivityManager *motionActivityManager;
+@property (nonatomic, strong) NSOperationQueue *operationQueue;
+@property (nonatomic, strong) NSTimer *timer;
+@property (nonatomic) int countTime;
+@property (nonatomic, assign) BOOL isRequesting;
@end
@implementation MapViewController
@@ -18,6 +42,21 @@
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = NSLocalizedString(@"lifelog.tapbar.map", nil);
+ [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.mapView attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
+ geocoder = [[CLGeocoder alloc] init];
+ [self setupLocation];
+ [self setupMapView];
+ previousLocation = nil;
+
+ if ([CMPedometer isStepCountingAvailable]) {
+ _pedometer = [[CMPedometer alloc] init];
+ }
+ if ([CMMotionActivityManager isActivityAvailable]) {
+ _motionActivityManager = [[CMMotionActivityManager alloc] init];
+ }
+ self.isRequesting = NO;
+ _countTime = 0;
+ self.lblUnitStep.text = NSLocalizedString(@"lifelog.home.unit.step", nil);
}
- (void)didReceiveMemoryWarning {
@@ -25,4 +64,131 @@
// Dispose of any resources that can be recreated.
}
+- (void)viewWillAppear:(BOOL)animated {
+ [super viewWillAppear:animated];
+ _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(countStep) userInfo:nil repeats:YES];
+ [_timer fire];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+ [super viewWillDisappear:animated];
+ [_timer invalidate];
+}
+
+#pragma mark - CLLocationManagerDelegate
+-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
+
+ CLLocation *newLocation = [locations lastObject];
+ if (previousLocation == nil) {
+ [self addAnnotationsOnMap:newLocation];
+ }
+ else {
+ CLLocationCoordinate2D area[2];
+ area[0] = previousLocation.coordinate;
+ area[1] = newLocation.coordinate;
+ MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:area count:2];
+ [_mapView addOverlay:polyLine];
+ }
+
+ previousLocation = newLocation;
+}
+
+- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
+{
+ NSLog(@"Cannot find the location.");
+}
+
+#pragma mark - MKMapViewDelegate
+- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id )overlay
+{
+ if ([overlay isKindOfClass:[MKPolyline class]]) {
+ MKPolylineRenderer *pr = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
+ pr.strokeColor = [UIColor redColor];
+ pr.lineWidth = 5;
+ return pr;
+ }
+ return nil;
+}
+
+#pragma mark - Functions Private
+
+- (void)addAnnotationsOnMap:(CLLocation *)locationToPoint {
+ MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
+ annotation.coordinate = locationToPoint.coordinate;
+ [geocoder reverseGeocodeLocation:locationToPoint completionHandler:^(NSArray *placemarks, NSError *error) {
+ if (error == nil && [placemarks count] >0) {
+ placemark = [placemarks firstObject];
+ NSDictionary *addressDict = placemark.addressDictionary;
+ annotation.title = [NSString stringWithFormat:@"%@", addressDict[@"Name"]];
+ [_mapView addAnnotation:annotation];
+ }
+ }];
+}
+
+- (void)setupLocation {
+ _locationManager = [[CLLocationManager alloc] init];
+ _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
+ _locationManager.delegate = self;
+ CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
+ if (status == kCLAuthorizationStatusNotDetermined || status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
+ [_locationManager requestWhenInUseAuthorization];
+ [_locationManager requestAlwaysAuthorization];
+ }
+ [_locationManager startUpdatingLocation];
+ [_locationManager startUpdatingHeading];
+}
+
+- (void)setupMapView {
+ _mapView.delegate = self;
+ _mapView.showsUserLocation = YES;
+ _mapView.mapType = MKMapTypeStandard;
+ _mapView.userTrackingMode = MKUserTrackingModeFollowWithHeading;
+}
+
+#pragma mark - Functions Private
+- (void)countStep
+{
+ _countTime++;
+ _lblTime.text = [self convertTime:_countTime];
+ _slider.value = _countTime;
+ if (self.isRequesting == YES) {
+ return;
+ }
+ if ([CMMotionActivityManager isActivityAvailable]) {
+ self.isRequesting = YES;
+ NSDate *endDate = [NSDate date];
+ NSDate *startDate = [endDate beginningAtMidnightOfDay];
+ MapViewController __weak *weakSelf = self;
+ dispatch_queue_t myQueue = dispatch_queue_create("mobileworld.jp.lifelog", NULL);
+ dispatch_async(myQueue, ^{
+ if (weakSelf == nil) {
+ return ;
+ }
+ [weakSelf.pedometer queryPedometerDataFromDate:startDate toDate:endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
+ NSInteger numberStep = [pedometerData.numberOfSteps integerValue];
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [weakSelf updateStepUI:numberStep];
+ });
+ }];
+ });
+ }
+}
+
+- (NSString *)convertTime:(int)time
+{
+ NSString *result = @"";
+ int hour = time/3600;
+ int minute = time/60;
+ int second = time % 60;
+ result = [NSString stringWithFormat:@"%02d:%02d:%02d", hour, minute, second];
+ return result;
+}
+
+- (void)updateStepUI:(NSInteger)numberStep
+{
+ // NSLog(@"Number of step: %ld", numberStep);
+ self.isRequesting = NO;
+ self.lblValueStep.text = [Utilities addCommaFromNumber:numberStep];
+}
+
@end
diff --git a/LifeLog/LifeLog/MapViewController.xib b/LifeLog/LifeLog/MapViewController.xib
index 1fcd6c9..417d257 100644
--- a/LifeLog/LifeLog/MapViewController.xib
+++ b/LifeLog/LifeLog/MapViewController.xib
@@ -1,16 +1,20 @@
-
+
-
+
+
+
+
+
@@ -18,7 +22,89 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LifeLog/LifeLog/ServerAPI.h b/LifeLog/LifeLog/ServerAPI.h
index adcb0ac..7f86f0b 100644
--- a/LifeLog/LifeLog/ServerAPI.h
+++ b/LifeLog/LifeLog/ServerAPI.h
@@ -27,6 +27,7 @@ extern NSString *const kNotificationToken;
#pragma mark - Home Screen Function
- (void)requestTopWithMode:(int)mode andDate:(NSString *)date CompletionHandler:(void (^)(TopObject *, NSError *)) completion;
+- (void)requestCreateLog:(int)mode withStep:(int)numStep startDate:(NSString *)startDate endDate:(NSString *)endDate CompletionHandler:(void (^)(NSError *))completion;
#pragma mark - History Screen Function
- (void) requestHistory:(NSString *)token atDate:(NSDate *)date withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryObject *, NSError *)) completion;
@@ -40,4 +41,6 @@ extern NSString *const kNotificationToken;
*/
- (void) requestTweetsList:(NSString *)token groupID: (int) groupID withPage:(int)page CompletionHandler:(void (^)(NSArray *, NSError *)) completion;
- (void) searchGroup:(NSString *)token withKey:(NSString *)key andPage:(int)page CompletionHandler:(void (^)(NSArray *, NSError *)) completion;
+#pragma mark - Common API
+- (void)refreshToken: (NSString *)userID CompletionHandler:(void (^)(NSString *, NSError *))completion;
@end
diff --git a/LifeLog/LifeLog/ServerAPI.m b/LifeLog/LifeLog/ServerAPI.m
index 7c6446e..ba65cf9 100644
--- a/LifeLog/LifeLog/ServerAPI.m
+++ b/LifeLog/LifeLog/ServerAPI.m
@@ -262,7 +262,7 @@ NSURLSessionDataTask * searchTask;
{
completion(nil, error);
}
- }];
+ }];
}
-(NSString *) convertIntToString : (int) type {
@@ -289,7 +289,7 @@ NSURLSessionDataTask * searchTask;
- (void)requestTopWithMode:(int)mode andDate:(NSString *)date CompletionHandler:(void (^)(TopObject *, NSError *)) completion
{
NSString * token = [[NSUserDefaults standardUserDefaults] stringForKey:kToken];
- NSString *url = [kServerAddress stringByAppendingFormat:@"/api/top/%d/%@", mode, date];
+ NSString *url = [kServerAddress stringByAppendingFormat:@"api/top/%d/%@", mode, date];
[self _request:url method:@"GET" token:token paras:nil completion:^(NSData *data, NSError *error) {
if (completion == NULL) {
@@ -347,9 +347,15 @@ NSURLSessionDataTask * searchTask;
if (message == nil) {
message = @"Unknown error";
}
- NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
- completion(nil, errorObject);
- [self checkToken:message];
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ [self requestTopWithMode:mode andDate:date CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, errorObject);
+ }
}
}
else
@@ -359,6 +365,46 @@ NSURLSessionDataTask * searchTask;
}];
}
+- (void)requestCreateLog:(int)mode withStep:(int)numStep startDate:(NSString *)startDate endDate:(NSString *)endDate CompletionHandler:(void (^)(NSError *))completion {
+ NSString * token = [[NSUserDefaults standardUserDefaults] stringForKey:kToken];
+ NSString *url = [kServerAddress stringByAppendingFormat:@"api/createLog"];
+ NSDictionary *dict = @{@"mode": [NSNumber numberWithInt:mode], @"numStep": [NSNumber numberWithInt:numStep], @"startTime": startDate, @"endTime": endDate};
+ [self _request:url method:@"POST" token:token paras:dict completion:^(NSData *data, NSError *error) {
+
+ if (completion == NULL) {
+ return ;
+ }
+
+ if (error == nil)
+ {
+ NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error];
+ int status = [dataResult[@"status"] intValue];
+ if (status == 1) { // status = 1 success
+ completion(nil);
+ }
+ else {
+ NSString *message = dataResult[@"message"];
+ if (message == nil) {
+ message = @"Unknown error";
+ }
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ [self requestCreateLog:mode withStep:numStep startDate:startDate endDate:endDate CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(errorObject);
+ }
+ }
+ }
+ else
+ {
+ completion(error);
+ }
+ }];
+}
+
#pragma mark - History Screen Function
- (void) requestHistory:(NSString *)token atDate:(NSDate *)date withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryObject *, NSError *)) completion {
NSString *url = [kServerAddress stringByAppendingFormat:@"/api/history/%@/%d", [self convertIntToString:type], mode];
@@ -383,9 +429,16 @@ NSURLSessionDataTask * searchTask;
if (message == nil) {
message = @"Unknown error";
}
- NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
- completion(nil, errorObject);
- [self checkToken:message];
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken];
+ [self requestHistory:tokenNew atDate:date withType:type andMode:mode CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, errorObject);
+ }
}
}
else
@@ -418,9 +471,16 @@ NSURLSessionDataTask * searchTask;
if (message == nil) {
message = @"Unknown error";
}
- NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
- completion(nil, errorObject);
- [self checkToken:message];
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken];
+ [self requestHistoryGraph:tokenNew withType:type andMode:mode CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, errorObject);
+ }
}
}
else
@@ -464,9 +524,16 @@ NSURLSessionDataTask * searchTask;
if (message == nil) {
message = @"Unknown error";
}
- NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
- completion(nil, errorObject);
- [self checkToken:message];
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken];
+ [self requestHistoryList:tokenNew withType:type andMode:mode AtPage:page CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, errorObject);
+ }
}
}
else
@@ -511,9 +578,19 @@ NSURLSessionDataTask * searchTask;
}
else {
NSString *message = dataResult[@"message"];
- NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
- completion(nil, errorObject);
- [self checkToken:message];
+ if (message == nil) {
+ message = @"Unknown error";
+ }
+
+ if ([message isEqualToString:@"Token is invalid"]) {
+ [self performSelectorOnMainThread:@selector(checkToken) withObject:nil waitUntilDone:YES];
+ NSString *tokenNew = [[NSUserDefaults standardUserDefaults] objectForKey:kToken];
+ [self requestTweetsList:tokenNew groupID:groupID withPage:page CompletionHandler:completion];
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, errorObject);
+ }
}
}
else
@@ -569,14 +646,59 @@ NSURLSessionDataTask * searchTask;
}];
}
+#pragma mark - Common API
+- (void)refreshToken: (NSString *)userID CompletionHandler:(void (^)(NSString *, NSError *))completion {
+ [self _request:[kServerAddress stringByAppendingFormat: @"refreshToken"] method:@"POST" token:@"" paras:@{@"userId":userID} completion:^(NSData *data, NSError *error) {
+
+ if (completion == NULL) {
+ return ;
+ }
+
+ if (error == nil)
+ {
+ NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error];
+
+ int status = [dataResult[@"status"] intValue];
+ if (status == 1) { // status = 1 success
+ NSArray *arrayResult = dataResult[@"result"];
+ if (arrayResult.count > 0) {
+ NSString *token = arrayResult[0];
+ completion(token, nil);
+ }
+ else {
+ NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":@"Unknown Error"}];
+ completion(nil, errorObject);
+ }
+
+ }
+ else { // status = 0 error
+ NSString *message = dataResult[@"message"];
+ if (message == nil) {
+ message = @"Unknown error";
+ }
+ NSError *loginFaild = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
+ completion(nil, loginFaild);
+ }
+ }
+ else
+ {
+ completion(nil, error);
+ }
+ }];
+}
+
#pragma mark - Private Function
-- (BOOL) checkToken:(NSString *)message {
- if ([message isEqualToString:@"Token is invalid"]) {
- [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationToken object:nil];
- return YES;
- }
- else {
- return NO;
+- (void) checkToken {
+ // [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationToken object:nil];
+ NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kUser];
+ User *user = (User *)[NSKeyedUnarchiver unarchiveObjectWithData:data];
+ if (user != nil) {
+ [self refreshToken:user.user_id CompletionHandler:^(NSString *token, NSError *error) {
+ if (error == nil) {
+ [[NSUserDefaults standardUserDefaults] setObject:token forKey:kToken];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+ }
+ }];
}
}
- (NSData *) _encodeDictionary: (NSDictionary *) dictionary
@@ -632,4 +754,11 @@ NSURLSessionDataTask * searchTask;
return task;
}
+-(void)waitUntilDone:(void(^)(void))waitBlock {
+ //use your statement or call method here
+ if(waitBlock){
+ waitBlock();
+ }
+}
+
@end