Because it is part of the utility of the app that the user can be clocked in and out fully unattended. If the user has to have the app running in the foreground, they might as well just fill in the information to enter into the logbook. However, people working in construction (the end users of our app) have a lot of reason to not be minding a phone but their feet and hands.
Post
Replies
Boosts
Views
Activity
My code is a Native Module called from a react native app, here is the native module code:
code-block
#import "RCTLocationDataManager.h"
#import <CoreLocation/CLLocationManager.h>
#import <React/RCTLog.h>
#import <CoreLocation/CLCircularRegion.h>
@implementation RCTLocationDataManager
{
CLLocationManager * locationManager;
NSDictionary * lastLocationEvent;
}
(dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE();
(BOOL)requiresMainQueueSetup
{
return YES; // only do this if your module exports constants or calls UIKit
}
//all methods currently async
RCT_EXPORT_METHOD(initialize:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
RCTLogInfo(@"Pretending to do something natively: initialize");
resolve(@(true));
}
RCT_EXPORT_METHOD(hasPermissions:(NSString *)permissionType
hasPermissionsWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
RCTLogInfo(@"Pretending to do something natively: hasPermissions %@", permissionType);
BOOL locationAllowed = [CLLocationManager locationServicesEnabled];
resolve(@(locationAllowed));
}
RCT_EXPORT_METHOD(requestPermissions:(NSString *)permissionType
requestPermissionsWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSArray *arbitraryReturnVal = @[@"testing..."];
// location
if (!locationManager) {
RCTLogInfo(@"init locationManager...");
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
locationManager.allowsBackgroundLocationUpdates = true;
locationManager.pausesLocationUpdatesAutomatically = true;
if ([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
[locationManager requestAlwaysAuthorization];
} else if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
for (CLRegion *region in locationManager.monitoredRegions)
{
[ locationManager stopMonitoringForRegion: region];
}
resolve(arbitraryReturnVal);
}
RCT_EXPORT_METHOD(startMonitoring:(NSArray *)projects)
{
NSLog(@"got projects :%@", projects);
locationManager.distanceFilter = 0;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
for (int i = 0; i < [projects count]; i++) {
NSDictionary* project = [projects objectAtIndex:i];
double longitude = [project[@"attributes"][@"longitude"] doubleValue];
double latitude = [project[@"attributes"][@"latitude"] doubleValue];
NSString *name = project[@"attributes"][@"name"];
CLLocationCoordinate2D centreLoc = {longitude, latitude};
CLLocationDistance regionRadius = [project[@"attributes"][@"geo_radius"] intValue];
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:centreLoc radius:500 identifier:name];
[locationManager startMonitoringForRegion:region];
NSLog(@"setup region:%@", region);
}
// [locationManager startUpdatingLocation];
// [locationManager startMonitoringSignificantLocationChanges];
NSLog(@"monotoring regions:%@", locationManager.monitoredRegions);
// CLCircularRegion *region = CLCircularRegion(CLLocationCoordinate2D(, ), 1000, "location1");
// region.notifyOnEntry = true;
// region.notifyOnExit = false;
// [locationManager startMonitoring:region];
}
(NSArray *)supportedEvents {
return @[@"significantLocationChange", @"didEnterRegion", @"didExitRegion"];
}
(void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(NSError *)error{
NSLog(@"Error with Updating");
}
-(void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
//Failed to recieve user's location
NSLog(@"failed to recived user's locatio");
}
(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion*)region {
RCTLogInfo(@"didEnterRegion : %@", region);
[self sendEventWithName:@"didEnterRegion" body:region.identifier];
}
(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion*)region {
RCTLogInfo(@"didExitRegion : %@", region);
[self sendEventWithName:@"didExitRegion" body:region.identifier];
}
(void)locationManager:(CLLocationManager *)manager
didDetermineState:(CLRegionState)state
forRegion:(CLRegion *)region {
RCTLogInfo(@"didDetermineState region %@", region);
switch (state) {
case CLRegionStateInside:
RCTLogInfo(@"didDetermineState inside region %@", region);
[self sendEventWithName:@"didEnterRegion" body:region.identifier];
break;
case CLRegionStateOutside:
RCTLogInfo(@"didDetermineState OUTSIDE region %@", region);
break;
case CLRegionStateUnknown:
RCTLogInfo(@"didDetermineState UNKNOWN %@", region);
break;
default:
break;
}
}
(void)locationManager:(CLLocationManager *)manager
// didStartMonitoringForRegion:(CLRegionState)state
forRegion:(CLRegion *)region {
RCTLogInfo(@"didStartMonitoringForRegion Already inside region? %@", region);
// if (state == CLRegionStateInside) {
// RCTLogInfo(@"Already inside region %@", region);
// [self locationManager:manager didEnterRegion:region];
// }
}
(void) locationManager:(CLLocationManager *) manager
monitoringDidFailFor:(CLRegion*)region
withError:(NSError *)error {
RCTLogInfo(@"Error monitoring region %@: %@", region, error);
}
@end