SwiftPedometerPlugin.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import Flutter
  2. import UIKit
  3. import CoreMotion
  4. public class SwiftPedometerPlugin: NSObject, FlutterPlugin {
  5. // Register Plugin
  6. public static func register(with registrar: FlutterPluginRegistrar) {
  7. let stepDetectionHandler = StepDetector()
  8. let stepDetectionChannel = FlutterEventChannel.init(name: "step_detection", binaryMessenger: registrar.messenger())
  9. stepDetectionChannel.setStreamHandler(stepDetectionHandler)
  10. let stepCountHandler = StepCounter()
  11. let stepCountChannel = FlutterEventChannel.init(name: "step_count", binaryMessenger: registrar.messenger())
  12. stepCountChannel.setStreamHandler(stepCountHandler)
  13. }
  14. }
  15. /// StepDetector, handles pedestrian status streaming
  16. public class StepDetector: NSObject, FlutterStreamHandler {
  17. private let pedometer = CMPedometer()
  18. private var running = false
  19. private var eventSink: FlutterEventSink?
  20. private func handleEvent(status: Int) {
  21. // If no eventSink to emit events to, do nothing (wait)
  22. if (eventSink == nil) {
  23. return
  24. }
  25. // Emit pedestrian status event to Flutter
  26. eventSink!(status)
  27. }
  28. public func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
  29. self.eventSink = eventSink
  30. if #available(iOS 10.0, *) {
  31. if (!CMPedometer.isPedometerEventTrackingAvailable()) {
  32. eventSink(FlutterError(code: "2", message: "Step Detection is not available", details: nil))
  33. }
  34. else if (!running) {
  35. running = true
  36. pedometer.startEventUpdates() {
  37. pedometerData, error in
  38. guard let pedometerData = pedometerData, error == nil else { return }
  39. DispatchQueue.main.async {
  40. self.handleEvent(status: pedometerData.type.rawValue)
  41. }
  42. }
  43. }
  44. } else {
  45. eventSink(FlutterError(code: "1", message: "Requires iOS 10.0 minimum", details: nil))
  46. }
  47. return nil
  48. }
  49. public func onCancel(withArguments arguments: Any?) -> FlutterError? {
  50. NotificationCenter.default.removeObserver(self)
  51. eventSink = nil
  52. if (running) {
  53. pedometer.stopUpdates()
  54. running = false
  55. }
  56. return nil
  57. }
  58. }
  59. /// StepCounter, handles step count streaming
  60. public class StepCounter: NSObject, FlutterStreamHandler {
  61. private let pedometer = CMPedometer()
  62. private var running = false
  63. private var eventSink: FlutterEventSink?
  64. private func handleEvent(count: Int) {
  65. // If no eventSink to emit events to, do nothing (wait)
  66. if (eventSink == nil) {
  67. return
  68. }
  69. // Emit step count event to Flutter
  70. eventSink!(count)
  71. }
  72. public func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
  73. self.eventSink = eventSink
  74. if #available(iOS 10.0, *) {
  75. if (!CMPedometer.isStepCountingAvailable()) {
  76. eventSink(FlutterError(code: "3", message: "Step Count is not available", details: nil))
  77. }
  78. else if (!running) {
  79. let systemUptime = ProcessInfo.processInfo.systemUptime;
  80. let timeNow = Date().timeIntervalSince1970
  81. let dateOfLastReboot = Date(timeIntervalSince1970: timeNow - systemUptime)
  82. running = true
  83. pedometer.startUpdates(from: dateOfLastReboot) {
  84. pedometerData, error in
  85. guard let pedometerData = pedometerData, error == nil else { return }
  86. DispatchQueue.main.async {
  87. self.handleEvent(count: pedometerData.numberOfSteps.intValue)
  88. }
  89. }
  90. }
  91. } else {
  92. eventSink(FlutterError(code: "1", message: "Requires iOS 10.0 minimum", details: nil))
  93. }
  94. return nil
  95. }
  96. public func onCancel(withArguments arguments: Any?) -> FlutterError? {
  97. NotificationCenter.default.removeObserver(self)
  98. eventSink = nil
  99. if (running) {
  100. pedometer.stopUpdates()
  101. running = false
  102. }
  103. return nil
  104. }
  105. }