123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- #if defined(__APPLE__)
- #include <TargetConditionals.h>
- #if TARGET_OS_IOS
-
- #include <CoreMotion/CoreMotion.h>
-
- #define ENABLE_STEP_COUNTER_LOGGING 1
- #if ENABLE_STEP_COUNTER_LOGGING
- #define STEP_COUNTER_LOG(...) NSLog(@"StepCounter - %@", [NSString stringWithFormat: __VA_ARGS__])
- #else
- #define STEP_COUNTER_LOG(...) {}
- #endif
-
- class iOSStepCounterWrapper
- {
- public:
- typedef void (*OnDataReceived) (int deviceId, int numberOfSteps);
-
- struct iOSStepCounterCallbacks
- {
- OnDataReceived dataReceived;
- };
-
-
- iOSStepCounterWrapper()
- {
- m_Pedometer = nullptr;
- m_Device = -1;
- }
-
- void Enable(int deviceId, iOSStepCounterCallbacks* callbacks)
- {
- if (IsEnabled())
- {
- STEP_COUNTER_LOG(@"Was already enabled?");
- if (m_Device != deviceId)
- STEP_COUNTER_LOG(@"Enabling with different device id? Expected %d, was %d. Are you creating more than one iOSStepCounter", m_Device, deviceId);
- }
- m_Pedometer = [[CMPedometer alloc]init];
- m_Callbacks = *callbacks;
- m_Device = deviceId;
- [m_Pedometer startPedometerUpdatesFromDate: [NSDate date] withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error)
- {
- // Note: We need to call our callback on the same thread the Unity scripting is operating
- dispatch_async(dispatch_get_main_queue(), ^{
- if (error != nil)
- {
- STEP_COUNTER_LOG(@"startPedometerUpdatesFromDate threw an error '%@', was it authorized?", [error localizedDescription]);
- if (m_Device != -1)
- Disable(m_Device);
- return;
- }
- // Guard against situation where device was disabled, any event which are received after that, should be ignored.
- if (m_Device == -1)
- return;
- m_Callbacks.dataReceived(m_Device, [pedometerData.numberOfSteps intValue]);
- });
- }];
- }
-
- bool Disable(int deviceId)
- {
- if (m_Pedometer == nullptr)
- return false;
- if (m_Device != deviceId)
- STEP_COUNTER_LOG(@"Disabling with wrong device id, expected %d, was %d", m_Device, deviceId);
- [m_Pedometer stopPedometerUpdates];
- m_Pedometer = nullptr;
- m_Device = -1;
- return true;
- }
-
- bool IsEnabled() const
- {
- return m_Pedometer != nullptr;
- }
-
- private:
- CMPedometer* m_Pedometer;
- iOSStepCounterCallbacks m_Callbacks;
- int m_Device;
- };
-
- static iOSStepCounterWrapper s_Wrapper;
- static const int kResultSuccess = 1;
- static const int kResultFailure = -1;
-
- extern "C" int _iOSStepCounterIsAvailable()
- {
- return [CMPedometer isStepCountingAvailable] ? 1 : 0;
- }
-
- extern "C" int _iOSStepCounterGetAuthorizationStatus()
- {
- if (@available(iOS 11.0, *))
- {
- return (int)[CMPedometer authorizationStatus];
- }
- return 0;
- }
-
- extern "C" int _iOSStepCounterEnable(int deviceId, iOSStepCounterWrapper::iOSStepCounterCallbacks* callbacks, int sizeOfCallbacks)
- {
- if (sizeof(iOSStepCounterWrapper::iOSStepCounterCallbacks) != sizeOfCallbacks)
- {
- STEP_COUNTER_LOG(@"iOSStepCounterCallbacks size mismatch, expected %lu was %d", sizeof(iOSStepCounterWrapper::iOSStepCounterCallbacks), sizeOfCallbacks);
- return kResultFailure;
- }
-
- if (_iOSStepCounterIsAvailable() == 0)
- {
- STEP_COUNTER_LOG(@"Step counting is not available");
- return kResultFailure;
- }
-
- NSString* motionUsage = @"NSMotionUsageDescription";
-
- if ([[NSBundle mainBundle] objectForInfoDictionaryKey: motionUsage] == nil)
- {
- STEP_COUNTER_LOG(@"%@ is missing in Info.plist, please enable Motion Usage in Input Settings", motionUsage);
- return kResultFailure;
- }
-
- if (@available(iOS 11.0, *))
- {
- if ([CMPedometer authorizationStatus] == CMAuthorizationStatusRestricted)
- {
- STEP_COUNTER_LOG(@"Step Counter was restricted.");
- return kResultFailure;
- }
-
- if ([CMPedometer authorizationStatus] == CMAuthorizationStatusDenied)
- {
- STEP_COUNTER_LOG(@"Step Counter was denied. Enable Motion & Fitness under app settings.");
- return kResultFailure;
- }
- // Do nothing for Authorized and NotDetermined
- }
-
- // Note: After installation this function will prompt a dialog asking about Motion & Fitness authorization
- // If user denies the prompt, there will be an error in startPedometerUpdatesFromDate callback
- // The dialog only appears once, not sure how to trigger it again, besides reinstalling app
- s_Wrapper.Enable(deviceId, callbacks);
-
- return kResultSuccess;
- }
-
- extern "C" int _iOSStepCounterDisable(int deviceId)
- {
- return s_Wrapper.Disable(deviceId) ? kResultSuccess : kResultFailure;
- }
-
- extern "C" int _iOSStepCounterIsEnabled(int deviceId)
- {
- return s_Wrapper.IsEnabled() ? 1 : 0;
- }
-
- #endif
- #endif
|