@josuelmm/capacitor-background-geolocation 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/JosuelmmCapacitorBackgroundGeolocation.podspec +34 -0
- package/LICENSE +17 -0
- package/NOTICE.md +32 -0
- package/Package.swift +45 -0
- package/README.md +402 -0
- package/android/build.gradle +79 -0
- package/android/proguard-rules.pro +1 -0
- package/android/src/main/AndroidManifest.xml +83 -0
- package/android/src/main/java/com/evgenii/jsevaluator/HandlerWrapper.java +18 -0
- package/android/src/main/java/com/evgenii/jsevaluator/JavaScriptInterface.java +22 -0
- package/android/src/main/java/com/evgenii/jsevaluator/JsEvaluator.java +133 -0
- package/android/src/main/java/com/evgenii/jsevaluator/JsFunctionCallFormatter.java +37 -0
- package/android/src/main/java/com/evgenii/jsevaluator/WebViewWrapper.java +71 -0
- package/android/src/main/java/com/evgenii/jsevaluator/interfaces/CallJavaResultInterface.java +8 -0
- package/android/src/main/java/com/evgenii/jsevaluator/interfaces/HandlerWrapperInterface.java +5 -0
- package/android/src/main/java/com/evgenii/jsevaluator/interfaces/JsCallback.java +10 -0
- package/android/src/main/java/com/evgenii/jsevaluator/interfaces/JsEvaluatorInterface.java +18 -0
- package/android/src/main/java/com/evgenii/jsevaluator/interfaces/WebViewWrapperInterface.java +14 -0
- package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/BackgroundGeolocationPlugin.java +898 -0
- package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/ConfigMapper.java +303 -0
- package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/HeadlessTaskRegistry.java +34 -0
- package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/JsEvaluatorTaskRunner.java +63 -0
- package/android/src/main/java/com/marianhello/bgloc/BackgroundGeolocationFacade.java +699 -0
- package/android/src/main/java/com/marianhello/bgloc/BootCompletedReceiver.java +103 -0
- package/android/src/main/java/com/marianhello/bgloc/Config.java +1155 -0
- package/android/src/main/java/com/marianhello/bgloc/ConnectivityListener.java +5 -0
- package/android/src/main/java/com/marianhello/bgloc/HttpPostService.java +362 -0
- package/android/src/main/java/com/marianhello/bgloc/LocationManager.java +138 -0
- package/android/src/main/java/com/marianhello/bgloc/PluginDelegate.java +45 -0
- package/android/src/main/java/com/marianhello/bgloc/PluginException.java +38 -0
- package/android/src/main/java/com/marianhello/bgloc/PostLocationTask.java +238 -0
- package/android/src/main/java/com/marianhello/bgloc/ResourceResolver.java +55 -0
- package/android/src/main/java/com/marianhello/bgloc/data/AbstractLocationTemplate.java +69 -0
- package/android/src/main/java/com/marianhello/bgloc/data/ArrayListLocationTemplate.java +88 -0
- package/android/src/main/java/com/marianhello/bgloc/data/BackgroundActivity.java +108 -0
- package/android/src/main/java/com/marianhello/bgloc/data/BackgroundLocation.java +1088 -0
- package/android/src/main/java/com/marianhello/bgloc/data/ConfigJsonMapper.java +211 -0
- package/android/src/main/java/com/marianhello/bgloc/data/ConfigurationDAO.java +13 -0
- package/android/src/main/java/com/marianhello/bgloc/data/DAOFactory.java +17 -0
- package/android/src/main/java/com/marianhello/bgloc/data/HashMapLocationTemplate.java +82 -0
- package/android/src/main/java/com/marianhello/bgloc/data/LocationDAO.java +27 -0
- package/android/src/main/java/com/marianhello/bgloc/data/LocationTemplate.java +12 -0
- package/android/src/main/java/com/marianhello/bgloc/data/LocationTemplateFactory.java +71 -0
- package/android/src/main/java/com/marianhello/bgloc/data/LocationTransform.java +19 -0
- package/android/src/main/java/com/marianhello/bgloc/data/SessionLocationDAO.java +18 -0
- package/android/src/main/java/com/marianhello/bgloc/data/provider/ContentProviderLocationDAO.java +406 -0
- package/android/src/main/java/com/marianhello/bgloc/data/provider/LocationContentProvider.java +321 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java +94 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java +227 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationContract.java +122 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationDAO.java +550 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java +189 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteSessionContract.java +74 -0
- package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteSessionLocationDAO.java +169 -0
- package/android/src/main/java/com/marianhello/bgloc/driving/DrivingEventsDetector.java +265 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/AbstractTaskRunner.java +15 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/ActivityTask.java +48 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/JsCallback.java +10 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/LocationTask.java +60 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/StationaryTask.java +25 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/Task.java +8 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/TaskRunner.java +5 -0
- package/android/src/main/java/com/marianhello/bgloc/headless/TaskRunnerFactory.java +8 -0
- package/android/src/main/java/com/marianhello/bgloc/http/UrlTemplateResolver.java +115 -0
- package/android/src/main/java/com/marianhello/bgloc/oem/BatteryOemHelper.java +214 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java +218 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +385 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +685 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/LocationProvider.java +32 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/LocationProviderFactory.java +47 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/ProviderDelegate.java +12 -0
- package/android/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +175 -0
- package/android/src/main/java/com/marianhello/bgloc/sensor/SensorFusionDetector.java +199 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationService.java +16 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceImpl.java +1531 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceInfo.java +6 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceInfoImpl.java +41 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceIntentBuilder.java +203 -0
- package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceProxy.java +156 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/AccountHelper.java +39 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/Authenticator.java +68 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/AuthenticatorService.java +28 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/BatchManager.java +311 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/NotificationHelper.java +148 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/SyncAdapter.java +301 -0
- package/android/src/main/java/com/marianhello/bgloc/sync/SyncService.java +68 -0
- package/android/src/main/java/com/marianhello/logging/DBLogReader.java +208 -0
- package/android/src/main/java/com/marianhello/logging/LogEntry.java +99 -0
- package/android/src/main/java/com/marianhello/logging/LoggerManager.java +70 -0
- package/android/src/main/java/com/marianhello/logging/UncaughtExceptionLogger.java +36 -0
- package/android/src/main/java/com/marianhello/utils/CloneHelper.java +22 -0
- package/android/src/main/java/com/marianhello/utils/Convert.java +56 -0
- package/android/src/main/java/com/marianhello/utils/TextUtils.java +72 -0
- package/android/src/main/java/com/marianhello/utils/ToneGenerator.java +68 -0
- package/android/src/main/java/org/apache/commons/io/Charsets.java +153 -0
- package/android/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java +344 -0
- package/android/src/main/java/org/chromium/content/browser/ThreadUtils.java +134 -0
- package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlExpression.java +398 -0
- package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlSelectStatement.java +671 -0
- package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlStatement.java +29 -0
- package/android/src/main/java/ru/andremoniy/utils/TextUtils.java +61 -0
- package/android/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/android/src/main/res/values/strings.xml +15 -0
- package/android/src/main/res/xml/authenticator.xml +7 -0
- package/android/src/main/res/xml/syncadapter.xml +9 -0
- package/dist/esm/definitions.d.ts +1052 -0
- package/dist/esm/definitions.js +142 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +23 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +92 -0
- package/dist/esm/web.js +242 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +415 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +418 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin-Bridging-Header.h +18 -0
- package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin.m +52 -0
- package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin.swift +750 -0
- package/ios/Tests/BackgroundGeolocationPluginTests/BackgroundGeolocationPluginTests.swift +12 -0
- package/ios/common/BackgroundGeolocation/CocoaLumberjack.h +1945 -0
- package/ios/common/BackgroundGeolocation/CocoaLumberjack.m +5255 -0
- package/ios/common/BackgroundGeolocation/FMDB.h +2357 -0
- package/ios/common/BackgroundGeolocation/FMDB.m +2672 -0
- package/ios/common/BackgroundGeolocation/FMDBLogger.h +42 -0
- package/ios/common/BackgroundGeolocation/FMDBLogger.m +264 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTUHeadingRequest.h +41 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTUHeadingRequest.m +68 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager+Internal.h +33 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager.h +178 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager.m +1025 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequest.h +103 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequest.m +238 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequestDefines.h +163 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTURequestIDGenerator.h +39 -0
- package/ios/common/BackgroundGeolocation/INTULocationManager/INTURequestIDGenerator.m +37 -0
- package/ios/common/BackgroundGeolocation/MAURAbstractLocationProvider.h +51 -0
- package/ios/common/BackgroundGeolocation/MAURAbstractLocationProvider.m +53 -0
- package/ios/common/BackgroundGeolocation/MAURActivity.h +23 -0
- package/ios/common/BackgroundGeolocation/MAURActivity.m +52 -0
- package/ios/common/BackgroundGeolocation/MAURActivityLocationProvider.h +18 -0
- package/ios/common/BackgroundGeolocation/MAURActivityLocationProvider.m +340 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.h +88 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +1193 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.h +46 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.m +283 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundTaskManager.h +25 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundTaskManager.m +105 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.h +99 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.m +636 -0
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.h +53 -0
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.m +54 -0
- package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.h +20 -0
- package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.m +550 -0
- package/ios/common/BackgroundGeolocation/MAURGeolocationOpenHelper.h +17 -0
- package/ios/common/BackgroundGeolocation/MAURGeolocationOpenHelper.m +124 -0
- package/ios/common/BackgroundGeolocation/MAURLocation.h +73 -0
- package/ios/common/BackgroundGeolocation/MAURLocation.m +392 -0
- package/ios/common/BackgroundGeolocation/MAURLocationContract.h +38 -0
- package/ios/common/BackgroundGeolocation/MAURLocationContract.m +39 -0
- package/ios/common/BackgroundGeolocation/MAURLocationManager.h +53 -0
- package/ios/common/BackgroundGeolocation/MAURLocationManager.m +305 -0
- package/ios/common/BackgroundGeolocation/MAURLogReader.h +26 -0
- package/ios/common/BackgroundGeolocation/MAURLogReader.m +122 -0
- package/ios/common/BackgroundGeolocation/MAURLogging.h +19 -0
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.h +53 -0
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.m +367 -0
- package/ios/common/BackgroundGeolocation/MAURProviderDelegate.h +52 -0
- package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.h +18 -0
- package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.m +138 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteConfigurationDAO.h +26 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteConfigurationDAO.m +335 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteHelper.h +57 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteHelper.m +93 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.h +52 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.m +520 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteOpenHelper.h +32 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteOpenHelper.m +276 -0
- package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.h +41 -0
- package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.m +137 -0
- package/ios/common/BackgroundGeolocation/MAURSessionLocationContract.h +29 -0
- package/ios/common/BackgroundGeolocation/MAURSessionLocationContract.m +31 -0
- package/ios/common/BackgroundGeolocation/MAURSessionLocationDAO.h +25 -0
- package/ios/common/BackgroundGeolocation/MAURSessionLocationDAO.m +153 -0
- package/ios/common/BackgroundGeolocation/MAURUncaughtExceptionLogger.h +20 -0
- package/ios/common/BackgroundGeolocation/MAURUncaughtExceptionLogger.m +62 -0
- package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.h +31 -0
- package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.m +107 -0
- package/ios/common/BackgroundGeolocation/Reachability.h +102 -0
- package/ios/common/BackgroundGeolocation/Reachability.m +475 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/README.md +170 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/ext/NSString+ZIMString.h +55 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/ext/NSString+ZIMString.m +47 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlDataManipulationCommand.h +27 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlExpression.h +250 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlExpression.m +259 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlSelectStatement.h +360 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlSelectStatement.m +427 -0
- package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlStatement.h +37 -0
- package/ios/common/BackgroundGeolocation/module.modulemap +16 -0
- package/package.json +82 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 JosueLMM
|
|
3
|
+
|
|
4
|
+
import Foundation
|
|
5
|
+
import Capacitor
|
|
6
|
+
import CoreLocation
|
|
7
|
+
import CoreMotion
|
|
8
|
+
import UIKit
|
|
9
|
+
import UserNotifications
|
|
10
|
+
import MAURBackgroundGeolocation
|
|
11
|
+
|
|
12
|
+
@objc(BackgroundGeolocationPlugin)
|
|
13
|
+
public class BackgroundGeolocationPlugin: CAPPlugin, CAPBridgedPlugin, MAURProviderDelegate {
|
|
14
|
+
public let identifier = "BackgroundGeolocationPlugin"
|
|
15
|
+
public let jsName = "BackgroundGeolocation"
|
|
16
|
+
public let pluginMethods: [CAPPluginMethod] = [
|
|
17
|
+
CAPPluginMethod(name: "configure", returnType: CAPPluginReturnPromise),
|
|
18
|
+
CAPPluginMethod(name: "start", returnType: CAPPluginReturnPromise),
|
|
19
|
+
CAPPluginMethod(name: "stop", returnType: CAPPluginReturnPromise),
|
|
20
|
+
CAPPluginMethod(name: "getCurrentLocation", returnType: CAPPluginReturnPromise),
|
|
21
|
+
CAPPluginMethod(name: "getStationaryLocation", returnType: CAPPluginReturnPromise),
|
|
22
|
+
CAPPluginMethod(name: "getLocations", returnType: CAPPluginReturnPromise),
|
|
23
|
+
CAPPluginMethod(name: "getValidLocations", returnType: CAPPluginReturnPromise),
|
|
24
|
+
CAPPluginMethod(name: "getValidLocationsAndDelete", returnType: CAPPluginReturnPromise),
|
|
25
|
+
CAPPluginMethod(name: "getConfig", returnType: CAPPluginReturnPromise),
|
|
26
|
+
CAPPluginMethod(name: "deleteLocation", returnType: CAPPluginReturnPromise),
|
|
27
|
+
CAPPluginMethod(name: "deleteAllLocations", returnType: CAPPluginReturnPromise),
|
|
28
|
+
CAPPluginMethod(name: "isLocationEnabled", returnType: CAPPluginReturnPromise),
|
|
29
|
+
CAPPluginMethod(name: "showAppSettings", returnType: CAPPluginReturnPromise),
|
|
30
|
+
CAPPluginMethod(name: "showLocationSettings", returnType: CAPPluginReturnPromise),
|
|
31
|
+
CAPPluginMethod(name: "openSettings", returnType: CAPPluginReturnPromise),
|
|
32
|
+
CAPPluginMethod(name: "watchLocationMode", returnType: CAPPluginReturnPromise),
|
|
33
|
+
CAPPluginMethod(name: "stopWatchingLocationMode", returnType: CAPPluginReturnPromise),
|
|
34
|
+
CAPPluginMethod(name: "getLogEntries", returnType: CAPPluginReturnPromise),
|
|
35
|
+
CAPPluginMethod(name: "checkStatus", returnType: CAPPluginReturnPromise),
|
|
36
|
+
CAPPluginMethod(name: "getDiagnostics", returnType: CAPPluginReturnPromise),
|
|
37
|
+
CAPPluginMethod(name: "getPluginVersion", returnType: CAPPluginReturnPromise),
|
|
38
|
+
CAPPluginMethod(name: "switchMode", returnType: CAPPluginReturnPromise),
|
|
39
|
+
CAPPluginMethod(name: "startTask", returnType: CAPPluginReturnPromise),
|
|
40
|
+
CAPPluginMethod(name: "endTask", returnType: CAPPluginReturnPromise),
|
|
41
|
+
CAPPluginMethod(name: "forceSync", returnType: CAPPluginReturnPromise),
|
|
42
|
+
CAPPluginMethod(name: "clearSync", returnType: CAPPluginReturnPromise),
|
|
43
|
+
CAPPluginMethod(name: "getPendingSyncCount", returnType: CAPPluginReturnPromise),
|
|
44
|
+
CAPPluginMethod(name: "startSession", returnType: CAPPluginReturnPromise),
|
|
45
|
+
CAPPluginMethod(name: "clearSession", returnType: CAPPluginReturnPromise),
|
|
46
|
+
CAPPluginMethod(name: "getSessionLocations", returnType: CAPPluginReturnPromise),
|
|
47
|
+
CAPPluginMethod(name: "getSessionLocationsCount", returnType: CAPPluginReturnPromise),
|
|
48
|
+
CAPPluginMethod(name: "triggerSOS", returnType: CAPPluginReturnPromise),
|
|
49
|
+
CAPPluginMethod(name: "isIgnoringBatteryOptimizations", returnType: CAPPluginReturnPromise),
|
|
50
|
+
CAPPluginMethod(name: "requestIgnoreBatteryOptimizations", returnType: CAPPluginReturnPromise),
|
|
51
|
+
CAPPluginMethod(name: "openBatterySettings", returnType: CAPPluginReturnPromise),
|
|
52
|
+
CAPPluginMethod(name: "openAutoStartSettings", returnType: CAPPluginReturnPromise),
|
|
53
|
+
CAPPluginMethod(name: "getManufacturerHelp", returnType: CAPPluginReturnPromise),
|
|
54
|
+
CAPPluginMethod(name: "requestBackgroundLocationPermission", returnType: CAPPluginReturnPromise),
|
|
55
|
+
CAPPluginMethod(name: "requestActivityRecognitionPermission", returnType: CAPPluginReturnPromise),
|
|
56
|
+
CAPPluginMethod(name: "requestNotificationPermission", returnType: CAPPluginReturnPromise),
|
|
57
|
+
CAPPluginMethod(name: "checkPermissions", returnType: CAPPluginReturnPromise),
|
|
58
|
+
CAPPluginMethod(name: "requestPermissions", returnType: CAPPluginReturnPromise),
|
|
59
|
+
CAPPluginMethod(name: "registerHeadlessTask", returnType: CAPPluginReturnPromise),
|
|
60
|
+
CAPPluginMethod(name: "removeAllListeners", returnType: CAPPluginReturnPromise)
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
private static let pluginVersion = "1.0.0"
|
|
64
|
+
|
|
65
|
+
private var facade: MAURBackgroundGeolocationFacade?
|
|
66
|
+
private var currentConfig: MAURConfig?
|
|
67
|
+
private var permissionHelper: PermissionRequestHelper?
|
|
68
|
+
private var lastLocationAt: Date?
|
|
69
|
+
|
|
70
|
+
override public func load() {
|
|
71
|
+
let f = MAURBackgroundGeolocationFacade()
|
|
72
|
+
f.delegate = self
|
|
73
|
+
facade = f
|
|
74
|
+
NotificationCenter.default.addObserver(self, selector: #selector(onAppForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
|
|
75
|
+
NotificationCenter.default.addObserver(self, selector: #selector(onAppBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
|
|
76
|
+
|
|
77
|
+
// v3.5 Phase 4 — sync + heartbeat notifications.
|
|
78
|
+
let nc = NotificationCenter.default
|
|
79
|
+
nc.addObserver(self, selector: #selector(onSyncStartN(_:)), name: NSNotification.Name(rawValue: MAURBackgroundSyncDidStartNotification), object: nil)
|
|
80
|
+
nc.addObserver(self, selector: #selector(onSyncSuccessN(_:)), name: NSNotification.Name(rawValue: MAURBackgroundSyncDidSucceedNotification), object: nil)
|
|
81
|
+
nc.addObserver(self, selector: #selector(onSyncErrorN(_:)), name: NSNotification.Name(rawValue: MAURBackgroundSyncDidFailNotification), object: nil)
|
|
82
|
+
nc.addObserver(self, selector: #selector(onSyncProgressN(_:)), name: NSNotification.Name(rawValue: MAURBackgroundSyncDidProgressNotification), object: nil)
|
|
83
|
+
nc.addObserver(self, selector: #selector(onHeartbeatN(_:)), name: NSNotification.Name(rawValue: MAURHeartbeatNotification), object: nil)
|
|
84
|
+
|
|
85
|
+
// v4.0 Phase 6 — driver-insight notifications.
|
|
86
|
+
nc.addObserver(self, selector: #selector(onTripStartN(_:)), name: NSNotification.Name(rawValue: MAURTripStartNotification), object: nil)
|
|
87
|
+
nc.addObserver(self, selector: #selector(onTripEndN(_:)), name: NSNotification.Name(rawValue: MAURTripEndNotification), object: nil)
|
|
88
|
+
nc.addObserver(self, selector: #selector(onMovingN(_:)), name: NSNotification.Name(rawValue: MAURMovingNotification), object: nil)
|
|
89
|
+
nc.addObserver(self, selector: #selector(onStoppedN(_:)), name: NSNotification.Name(rawValue: MAURStoppedNotification), object: nil)
|
|
90
|
+
nc.addObserver(self, selector: #selector(onSpeedingN(_:)), name: NSNotification.Name(rawValue: MAURSpeedingNotification), object: nil)
|
|
91
|
+
nc.addObserver(self, selector: #selector(onProviderChangeN(_:)), name: NSNotification.Name(rawValue: MAURProviderChangeNotification), object: nil)
|
|
92
|
+
nc.addObserver(self, selector: #selector(onSOSN(_:)), name: NSNotification.Name(rawValue: MAURSOSNotification), object: nil)
|
|
93
|
+
|
|
94
|
+
// v4.1 GPS-derived sensor-like events.
|
|
95
|
+
nc.addObserver(self, selector: #selector(onHardBrakeN(_:)), name: NSNotification.Name(rawValue: MAURHardBrakeNotification), object: nil)
|
|
96
|
+
nc.addObserver(self, selector: #selector(onRapidAccelerationN(_:)), name: NSNotification.Name(rawValue: MAURRapidAccelerationNotification), object: nil)
|
|
97
|
+
nc.addObserver(self, selector: #selector(onSharpTurnN(_:)), name: NSNotification.Name(rawValue: MAURSharpTurnNotification), object: nil)
|
|
98
|
+
nc.addObserver(self, selector: #selector(onPossibleCrashN(_:)), name: NSNotification.Name(rawValue: MAURPossibleCrashNotification), object: nil)
|
|
99
|
+
|
|
100
|
+
// v4.2 sensor fusion.
|
|
101
|
+
nc.addObserver(self, selector: #selector(onPhoneUsageWhileDrivingN(_:)), name: NSNotification.Name(rawValue: MAURPhoneUsageWhileDrivingNotification), object: nil)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
deinit {
|
|
105
|
+
NotificationCenter.default.removeObserver(self)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// MARK: - App lifecycle bridge
|
|
109
|
+
|
|
110
|
+
@objc private func onAppForeground() {
|
|
111
|
+
facade?.switchMode(MAURForegroundMode)
|
|
112
|
+
notifyListeners("foreground", data: [:])
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@objc private func onAppBackground() {
|
|
116
|
+
facade?.switchMode(MAURBackgroundMode)
|
|
117
|
+
notifyListeners("background", data: [:])
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// MARK: - Bridge methods
|
|
121
|
+
|
|
122
|
+
@objc func configure(_ call: CAPPluginCall) {
|
|
123
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
124
|
+
let opts = call.options ?? [:]
|
|
125
|
+
let cfg = MAURConfig.fromDictionary(opts)
|
|
126
|
+
currentConfig = cfg
|
|
127
|
+
do {
|
|
128
|
+
try facade.configure(cfg)
|
|
129
|
+
call.resolve()
|
|
130
|
+
} catch {
|
|
131
|
+
let nsErr = error as NSError
|
|
132
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@objc func start(_ call: CAPPluginCall) {
|
|
137
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
138
|
+
do {
|
|
139
|
+
try facade.start()
|
|
140
|
+
// `start` event is emitted by MAURProviderDelegate.onLocationResume.
|
|
141
|
+
call.resolve()
|
|
142
|
+
} catch {
|
|
143
|
+
let nsErr = error as NSError
|
|
144
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@objc func stop(_ call: CAPPluginCall) {
|
|
149
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
150
|
+
do {
|
|
151
|
+
try facade.stop()
|
|
152
|
+
// `stop` event is emitted by MAURProviderDelegate.onLocationPause.
|
|
153
|
+
call.resolve()
|
|
154
|
+
} catch {
|
|
155
|
+
let nsErr = error as NSError
|
|
156
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@objc func getCurrentLocation(_ call: CAPPluginCall) {
|
|
161
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
162
|
+
let timeout = call.getInt("timeout") ?? Int(Int32.max)
|
|
163
|
+
let maximumAge = call.getInt("maximumAge").map { Int64($0) } ?? Int64.max
|
|
164
|
+
let highAccuracy = call.getBool("enableHighAccuracy") ?? false
|
|
165
|
+
do {
|
|
166
|
+
let location = try facade.getCurrentLocation(Int32(timeout), maximumAge: maximumAge, enableHighAccuracy: highAccuracy)
|
|
167
|
+
call.resolve(location.toDictionary() as? [String: Any] ?? [:])
|
|
168
|
+
} catch {
|
|
169
|
+
let nsErr = error as NSError
|
|
170
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@objc func getStationaryLocation(_ call: CAPPluginCall) {
|
|
175
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
176
|
+
if let loc = facade.getStationaryLocation() {
|
|
177
|
+
call.resolve(loc.toDictionary() as? [String: Any] ?? [:])
|
|
178
|
+
} else {
|
|
179
|
+
// TS contract is `Location | null` — resolve with no payload so the
|
|
180
|
+
// JS bridge surfaces `null`, matching Android's `call.resolve()`.
|
|
181
|
+
call.resolve()
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@objc func getLocations(_ call: CAPPluginCall) {
|
|
186
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
187
|
+
let locations = facade.getLocations() as? [MAURLocation] ?? []
|
|
188
|
+
let arr = locations.compactMap { $0.toDictionaryWithId() as? [String: Any] }
|
|
189
|
+
call.resolve(["locations": arr])
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@objc func getValidLocations(_ call: CAPPluginCall) {
|
|
193
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
194
|
+
let locations = facade.getValidLocations() as? [MAURLocation] ?? []
|
|
195
|
+
let arr = locations.compactMap { $0.toDictionaryWithId() as? [String: Any] }
|
|
196
|
+
call.resolve(["locations": arr])
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@objc func getValidLocationsAndDelete(_ call: CAPPluginCall) {
|
|
200
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
201
|
+
let locations = facade.getValidLocationsAndDelete() as? [MAURLocation] ?? []
|
|
202
|
+
let arr = locations.compactMap { $0.toDictionaryWithId() as? [String: Any] }
|
|
203
|
+
call.resolve(["locations": arr])
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@objc func getConfig(_ call: CAPPluginCall) {
|
|
207
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
208
|
+
let cfg = facade.getConfig()
|
|
209
|
+
let dict = cfg?.toDictionary() as? [String: Any] ?? [:]
|
|
210
|
+
call.resolve(dict)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@objc func deleteLocation(_ call: CAPPluginCall) {
|
|
214
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
215
|
+
guard let locationId = call.getInt("locationId") else {
|
|
216
|
+
call.reject("locationId required"); return
|
|
217
|
+
}
|
|
218
|
+
do {
|
|
219
|
+
try facade.delete(NSNumber(value: locationId))
|
|
220
|
+
call.resolve()
|
|
221
|
+
} catch {
|
|
222
|
+
let nsErr = error as NSError
|
|
223
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@objc func deleteAllLocations(_ call: CAPPluginCall) {
|
|
228
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
229
|
+
do {
|
|
230
|
+
try facade.deleteAllLocations()
|
|
231
|
+
call.resolve()
|
|
232
|
+
} catch {
|
|
233
|
+
let nsErr = error as NSError
|
|
234
|
+
call.reject(nsErr.localizedDescription, String(nsErr.code))
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@objc func isLocationEnabled(_ call: CAPPluginCall) {
|
|
239
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
240
|
+
call.resolve(["enabled": facade.locationServicesEnabled()])
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@objc func showAppSettings(_ call: CAPPluginCall) {
|
|
244
|
+
facade?.showAppSettings()
|
|
245
|
+
call.resolve()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@objc func showLocationSettings(_ call: CAPPluginCall) {
|
|
249
|
+
facade?.showLocationSettings()
|
|
250
|
+
call.resolve()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@objc func openSettings(_ call: CAPPluginCall) {
|
|
254
|
+
// Alias of showAppSettings — keeps parity with the cross-platform TS contract.
|
|
255
|
+
facade?.showAppSettings()
|
|
256
|
+
call.resolve()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@objc func watchLocationMode(_ call: CAPPluginCall) {
|
|
260
|
+
// iOS has no separate "mode watcher". Permission/status changes flow through
|
|
261
|
+
// onAuthorizationChanged -> "authorization" event. This is a no-op resolve.
|
|
262
|
+
call.resolve()
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@objc func stopWatchingLocationMode(_ call: CAPPluginCall) {
|
|
266
|
+
call.resolve()
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@objc func getLogEntries(_ call: CAPPluginCall) {
|
|
270
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
271
|
+
let limit = call.getInt("limit") ?? 0
|
|
272
|
+
let fromId = call.getInt("fromId") ?? 0
|
|
273
|
+
let minLevel = call.getString("minLevel") ?? "DEBUG"
|
|
274
|
+
let logs = facade.getLogEntries(limit, fromLogEntryId: fromId, minLogLevelFromString: minLevel) as? [Any] ?? []
|
|
275
|
+
call.resolve(["entries": logs])
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@objc func checkStatus(_ call: CAPPluginCall) {
|
|
279
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
280
|
+
let isRunning = facade.isStarted()
|
|
281
|
+
let enabled = facade.locationServicesEnabled()
|
|
282
|
+
let auth = facade.authorizationStatus()
|
|
283
|
+
call.resolve([
|
|
284
|
+
"isRunning": isRunning,
|
|
285
|
+
"locationServicesEnabled": enabled,
|
|
286
|
+
"authorization": auth.rawValue
|
|
287
|
+
])
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@objc func getDiagnostics(_ call: CAPPluginCall) {
|
|
291
|
+
var d: [String: Any] = [:]
|
|
292
|
+
d["isRunning"] = facade?.isStarted() ?? false
|
|
293
|
+
d["locationServicesEnabled"] = facade?.locationServicesEnabled() ?? false
|
|
294
|
+
// iOS has no boot-time auto-start equivalent. Expose for cross-platform shape.
|
|
295
|
+
d["startOnBoot"] = false
|
|
296
|
+
|
|
297
|
+
// Pending sync (best-effort).
|
|
298
|
+
let pending = MAURSQLiteLocationDAO.sharedInstance().getLocationsForSyncCount()
|
|
299
|
+
d["pendingSyncCount"] = pending?.intValue ?? 0
|
|
300
|
+
|
|
301
|
+
if let last = lastLocationAt {
|
|
302
|
+
d["lastLocationAt"] = Int64(last.timeIntervalSince1970 * 1000)
|
|
303
|
+
} else {
|
|
304
|
+
d["lastLocationAt"] = NSNull()
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Precise location (iOS 14+).
|
|
308
|
+
if #available(iOS 14.0, *) {
|
|
309
|
+
let lm = CLLocationManager()
|
|
310
|
+
d["preciseLocationEnabled"] = (lm.accuracyAuthorization == .fullAccuracy)
|
|
311
|
+
} else {
|
|
312
|
+
d["preciseLocationEnabled"] = true
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
d["backgroundRefreshStatus"] = Self.backgroundRefreshText()
|
|
316
|
+
d["lowPowerModeEnabled"] = ProcessInfo.processInfo.isLowPowerModeEnabled
|
|
317
|
+
d["motionPermissionStatus"] = Self.motionPermissionText()
|
|
318
|
+
d["authorizationStatusText"] = Self.authorizationStatusText(Self.currentAuthorizationStatus())
|
|
319
|
+
|
|
320
|
+
call.resolve(d)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
@objc func getPluginVersion(_ call: CAPPluginCall) {
|
|
324
|
+
call.resolve(["version": Self.pluginVersion])
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@objc func switchMode(_ call: CAPPluginCall) {
|
|
328
|
+
guard let facade = facade else { call.reject("facade not initialized"); return }
|
|
329
|
+
let raw = call.getInt("mode") ?? Int(MAURForegroundMode.rawValue)
|
|
330
|
+
let mode: MAUROperationalMode = (raw == Int(MAURBackgroundMode.rawValue)) ? MAURBackgroundMode : MAURForegroundMode
|
|
331
|
+
facade.switchMode(mode)
|
|
332
|
+
call.resolve()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
@objc func startTask(_ call: CAPPluginCall) {
|
|
336
|
+
let key = MAURBackgroundTaskManager.sharedTasks().beginTask()
|
|
337
|
+
call.resolve(["taskKey": key])
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
@objc func endTask(_ call: CAPPluginCall) {
|
|
341
|
+
let key = call.getInt("taskKey") ?? 0
|
|
342
|
+
MAURBackgroundTaskManager.sharedTasks().endTask(withKey: UInt(key))
|
|
343
|
+
call.resolve()
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
@objc func forceSync(_ call: CAPPluginCall) {
|
|
347
|
+
facade?.forceSync()
|
|
348
|
+
call.resolve()
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@objc func clearSync(_ call: CAPPluginCall) {
|
|
352
|
+
facade?.clearSync()
|
|
353
|
+
call.resolve()
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
@objc func getPendingSyncCount(_ call: CAPPluginCall) {
|
|
357
|
+
let count = facade?.getPendingSyncCount() ?? 0
|
|
358
|
+
call.resolve(["count": count])
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@objc func startSession(_ call: CAPPluginCall) {
|
|
362
|
+
facade?.startSession()
|
|
363
|
+
call.resolve()
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@objc func clearSession(_ call: CAPPluginCall) {
|
|
367
|
+
facade?.clearSession()
|
|
368
|
+
call.resolve()
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
@objc func getSessionLocations(_ call: CAPPluginCall) {
|
|
372
|
+
let locations = facade?.getSessionLocations() as? [MAURLocation] ?? []
|
|
373
|
+
let arr = locations.compactMap { $0.toDictionaryWithId() as? [String: Any] }
|
|
374
|
+
call.resolve(["locations": arr])
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@objc func getSessionLocationsCount(_ call: CAPPluginCall) {
|
|
378
|
+
let count = facade?.getSessionLocationsCount() ?? 0
|
|
379
|
+
call.resolve(["count": count])
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
@objc func triggerSOS(_ call: CAPPluginCall) {
|
|
383
|
+
// Facade attaches the latest location and posts MAURSOSNotification, which we
|
|
384
|
+
// forward via onSOSN(_:) below — keeps the payload-merge logic in a single place.
|
|
385
|
+
let payload = call.getObject("payload")
|
|
386
|
+
facade?.triggerSOS(payload)
|
|
387
|
+
call.resolve()
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// MARK: - Battery / OEM helpers (iOS no-ops)
|
|
391
|
+
|
|
392
|
+
@objc func isIgnoringBatteryOptimizations(_ call: CAPPluginCall) {
|
|
393
|
+
call.resolve(["whitelisted": true])
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
@objc func requestIgnoreBatteryOptimizations(_ call: CAPPluginCall) {
|
|
397
|
+
call.resolve(["whitelisted": true])
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@objc func openBatterySettings(_ call: CAPPluginCall) {
|
|
401
|
+
// iOS has no Battery Settings deeplink. Best-effort: app settings.
|
|
402
|
+
if let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) {
|
|
403
|
+
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
404
|
+
}
|
|
405
|
+
call.resolve()
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
@objc func openAutoStartSettings(_ call: CAPPluginCall) {
|
|
409
|
+
// No per-OEM auto-start screen on iOS. Report opened=false to let JS render help.
|
|
410
|
+
call.resolve([
|
|
411
|
+
"opened": false,
|
|
412
|
+
"manufacturer": "apple",
|
|
413
|
+
"screen": ""
|
|
414
|
+
])
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
@objc func getManufacturerHelp(_ call: CAPPluginCall) {
|
|
418
|
+
// Consumer apps will render their own copy. Return an empty list to keep the
|
|
419
|
+
// cross-platform shape stable.
|
|
420
|
+
call.resolve([
|
|
421
|
+
"manufacturer": "apple",
|
|
422
|
+
"steps": [] as [String]
|
|
423
|
+
])
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// MARK: - Runtime permission helpers (cross-platform shims)
|
|
427
|
+
|
|
428
|
+
@objc func requestBackgroundLocationPermission(_ call: CAPPluginCall) {
|
|
429
|
+
// iOS folds background into "Always" — there's no separate gate.
|
|
430
|
+
call.resolve(["granted": true, "notRequired": true])
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
@objc func requestActivityRecognitionPermission(_ call: CAPPluginCall) {
|
|
434
|
+
// Probe motion availability so the consumer sees a faithful "granted" flag.
|
|
435
|
+
var granted = true
|
|
436
|
+
if #available(iOS 11.0, *) {
|
|
437
|
+
if CMMotionActivityManager.isActivityAvailable() {
|
|
438
|
+
switch CMMotionActivityManager.authorizationStatus() {
|
|
439
|
+
case .authorized: granted = true
|
|
440
|
+
case .denied,
|
|
441
|
+
.restricted: granted = false
|
|
442
|
+
case .notDetermined: granted = true
|
|
443
|
+
@unknown default: granted = true
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
call.resolve(["granted": granted, "notRequired": true])
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
@objc func requestNotificationPermission(_ call: CAPPluginCall) {
|
|
451
|
+
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, _ in
|
|
452
|
+
call.resolve(["granted": granted, "notRequired": false])
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/// Android-only feature. iOS does not allow running JS in a killed-app
|
|
457
|
+
/// scenario the way Android's `JsEvaluator` does. The call resolves so
|
|
458
|
+
/// cross-platform code stays portable. Use the regular `addListener`
|
|
459
|
+
/// callbacks on iOS — they are delivered as long as the app is running
|
|
460
|
+
/// in the background (which on iOS is the only state where locations
|
|
461
|
+
/// are produced anyway).
|
|
462
|
+
@objc func registerHeadlessTask(_ call: CAPPluginCall) {
|
|
463
|
+
call.resolve()
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
@objc override public func removeAllListeners(_ call: CAPPluginCall) {
|
|
467
|
+
super.removeAllListeners(call)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// MARK: - Permissions (Capacitor standard)
|
|
471
|
+
|
|
472
|
+
@objc override public func checkPermissions(_ call: CAPPluginCall) {
|
|
473
|
+
let status = Self.currentAuthorizationStatus()
|
|
474
|
+
call.resolve(["location": Self.permissionState(for: status)])
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
@objc override public func requestPermissions(_ call: CAPPluginCall) {
|
|
478
|
+
let status = Self.currentAuthorizationStatus()
|
|
479
|
+
if status != .notDetermined {
|
|
480
|
+
call.resolve(["location": Self.permissionState(for: status)])
|
|
481
|
+
return
|
|
482
|
+
}
|
|
483
|
+
let helper = PermissionRequestHelper { [weak self] result in
|
|
484
|
+
call.resolve(["location": BackgroundGeolocationPlugin.permissionState(for: result)])
|
|
485
|
+
self?.permissionHelper = nil
|
|
486
|
+
}
|
|
487
|
+
permissionHelper = helper
|
|
488
|
+
helper.start()
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private static func currentAuthorizationStatus() -> CLAuthorizationStatus {
|
|
492
|
+
if #available(iOS 14.0, *) {
|
|
493
|
+
return CLLocationManager().authorizationStatus
|
|
494
|
+
}
|
|
495
|
+
return CLLocationManager.authorizationStatus()
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
private static func permissionState(for status: CLAuthorizationStatus) -> String {
|
|
499
|
+
switch status {
|
|
500
|
+
case .notDetermined: return "prompt"
|
|
501
|
+
case .denied, .restricted: return "denied"
|
|
502
|
+
case .authorizedAlways, .authorizedWhenInUse: return "granted"
|
|
503
|
+
@unknown default: return "prompt"
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
private static func authorizationStatusText(_ status: CLAuthorizationStatus) -> String {
|
|
508
|
+
switch status {
|
|
509
|
+
case .notDetermined: return "notDetermined"
|
|
510
|
+
case .restricted: return "restricted"
|
|
511
|
+
case .denied: return "denied"
|
|
512
|
+
case .authorizedAlways: return "authorizedAlways"
|
|
513
|
+
case .authorizedWhenInUse: return "authorizedWhenInUse"
|
|
514
|
+
@unknown default: return "unknown"
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
private static func backgroundRefreshText() -> String {
|
|
519
|
+
switch UIApplication.shared.backgroundRefreshStatus {
|
|
520
|
+
case .available: return "available"
|
|
521
|
+
case .denied: return "denied"
|
|
522
|
+
case .restricted: return "restricted"
|
|
523
|
+
@unknown default: return "unknown"
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
private static func motionPermissionText() -> String {
|
|
528
|
+
if !CMMotionActivityManager.isActivityAvailable() { return "restricted" }
|
|
529
|
+
if #available(iOS 11.0, *) {
|
|
530
|
+
switch CMMotionActivityManager.authorizationStatus() {
|
|
531
|
+
case .notDetermined: return "notDetermined"
|
|
532
|
+
case .restricted: return "restricted"
|
|
533
|
+
case .denied: return "denied"
|
|
534
|
+
case .authorized: return "authorized"
|
|
535
|
+
@unknown default: return "notDetermined"
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return "notDetermined"
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// MARK: - MAURProviderDelegate
|
|
542
|
+
|
|
543
|
+
public func onAuthorizationChanged(_ authStatus: MAURLocationAuthorizationStatus) {
|
|
544
|
+
notifyListeners("authorization", data: ["status": authStatus.rawValue])
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
public func onLocationChanged(_ location: MAURLocation!) {
|
|
548
|
+
lastLocationAt = Date()
|
|
549
|
+
guard let dict = location.toDictionaryWithId() as? [String: Any] else { return }
|
|
550
|
+
notifyListeners("location", data: dict)
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
public func onStationaryChanged(_ location: MAURLocation!) {
|
|
554
|
+
guard let dict = location.toDictionaryWithId() as? [String: Any] else { return }
|
|
555
|
+
notifyListeners("stationary", data: dict)
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
public func onLocationPause() {
|
|
559
|
+
notifyListeners("stop", data: [:])
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
public func onLocationResume() {
|
|
563
|
+
notifyListeners("start", data: [:])
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
public func onActivityChanged(_ activity: MAURActivity!) {
|
|
567
|
+
guard let dict = activity.toDictionary() as? [String: Any] else { return }
|
|
568
|
+
notifyListeners("activity", data: dict)
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
public func onAbortRequested() {
|
|
572
|
+
notifyListeners("abort_requested", data: [:])
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
public func onHttpAuthorization() {
|
|
576
|
+
notifyListeners("http_authorization", data: [:])
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
public func onError(_ error: Error!) {
|
|
580
|
+
let nsErr = error as NSError?
|
|
581
|
+
notifyListeners("error", data: [
|
|
582
|
+
"code": nsErr?.code ?? -1,
|
|
583
|
+
"message": nsErr?.localizedDescription ?? "unknown error"
|
|
584
|
+
])
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// MARK: - Notification observers (sync / heartbeat / driving)
|
|
588
|
+
|
|
589
|
+
@objc private func onSyncStartN(_ note: Notification) {
|
|
590
|
+
notifyListeners("syncStart", data: [:])
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
@objc private func onSyncSuccessN(_ note: Notification) {
|
|
594
|
+
let sent = (note.userInfo?["sent"] as? NSNumber)?.intValue ?? 0
|
|
595
|
+
notifyListeners("syncSuccess", data: ["sent": sent])
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
@objc private func onSyncErrorN(_ note: Notification) {
|
|
599
|
+
let status = (note.userInfo?["httpStatus"] as? NSNumber)?.intValue ?? 0
|
|
600
|
+
let msg = (note.userInfo?["message"] as? String) ?? ""
|
|
601
|
+
notifyListeners("syncError", data: ["httpStatus": status, "message": msg])
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
@objc private func onSyncProgressN(_ note: Notification) {
|
|
605
|
+
let progress = (note.userInfo?["progress"] as? NSNumber)?.intValue ?? 0
|
|
606
|
+
notifyListeners("syncProgress", data: ["progress": progress])
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
@objc private func onHeartbeatN(_ note: Notification) {
|
|
610
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
611
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
612
|
+
notifyListeners("heartbeat", data: dict)
|
|
613
|
+
} else {
|
|
614
|
+
notifyListeners("heartbeat", data: [:])
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
@objc private func onTripStartN(_ note: Notification) {
|
|
619
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
620
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
621
|
+
notifyListeners("tripStart", data: dict)
|
|
622
|
+
} else {
|
|
623
|
+
notifyListeners("tripStart", data: [:])
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
@objc private func onTripEndN(_ note: Notification) {
|
|
628
|
+
var p: [String: Any] = [:]
|
|
629
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
630
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
631
|
+
p["location"] = dict
|
|
632
|
+
} else {
|
|
633
|
+
p["location"] = NSNull()
|
|
634
|
+
}
|
|
635
|
+
p["distance"] = (note.userInfo?["distance"] as? NSNumber)?.doubleValue ?? 0
|
|
636
|
+
p["durationMs"] = (note.userInfo?["durationMs"] as? NSNumber)?.int64Value ?? 0
|
|
637
|
+
notifyListeners("tripEnd", data: p)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
@objc private func onMovingN(_ note: Notification) {
|
|
641
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
642
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
643
|
+
notifyListeners("moving", data: dict)
|
|
644
|
+
} else {
|
|
645
|
+
notifyListeners("moving", data: [:])
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
@objc private func onStoppedN(_ note: Notification) {
|
|
650
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
651
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
652
|
+
notifyListeners("stopped", data: dict)
|
|
653
|
+
} else {
|
|
654
|
+
notifyListeners("stopped", data: [:])
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
@objc private func onSpeedingN(_ note: Notification) {
|
|
659
|
+
var p: [String: Any] = [:]
|
|
660
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
661
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
662
|
+
p["location"] = dict
|
|
663
|
+
} else {
|
|
664
|
+
p["location"] = NSNull()
|
|
665
|
+
}
|
|
666
|
+
p["speedKmh"] = (note.userInfo?["speedKmh"] as? NSNumber)?.doubleValue ?? 0
|
|
667
|
+
p["limitKmh"] = (note.userInfo?["limitKmh"] as? NSNumber)?.doubleValue ?? 0
|
|
668
|
+
notifyListeners("speeding", data: p)
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
@objc private func onProviderChangeN(_ note: Notification) {
|
|
672
|
+
let provider = (note.userInfo?["provider"] as? String) ?? ""
|
|
673
|
+
notifyListeners("providerChange", data: ["provider": provider])
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
@objc private func onSOSN(_ note: Notification) {
|
|
677
|
+
var p: [String: Any] = [:]
|
|
678
|
+
if let userPayload = note.userInfo?["payload"] as? [String: Any] {
|
|
679
|
+
for (k, v) in userPayload { p[k] = v }
|
|
680
|
+
}
|
|
681
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
682
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
683
|
+
p["location"] = dict
|
|
684
|
+
} else if p["location"] == nil {
|
|
685
|
+
p["location"] = NSNull()
|
|
686
|
+
}
|
|
687
|
+
notifyListeners("sos", data: p)
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
private func emitDrivingEvent(_ name: String, note: Notification) {
|
|
691
|
+
var p: [String: Any] = [:]
|
|
692
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
693
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
694
|
+
p["location"] = dict
|
|
695
|
+
} else {
|
|
696
|
+
p["location"] = NSNull()
|
|
697
|
+
}
|
|
698
|
+
p["value"] = (note.userInfo?["value"] as? NSNumber)?.doubleValue ?? 0
|
|
699
|
+
if let source = note.userInfo?["source"] as? String { p["source"] = source }
|
|
700
|
+
notifyListeners(name, data: p)
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
@objc private func onHardBrakeN(_ note: Notification) { emitDrivingEvent("hardBrake", note: note) }
|
|
704
|
+
@objc private func onRapidAccelerationN(_ note: Notification) { emitDrivingEvent("rapidAcceleration", note: note) }
|
|
705
|
+
@objc private func onSharpTurnN(_ note: Notification) { emitDrivingEvent("sharpTurn", note: note) }
|
|
706
|
+
@objc private func onPossibleCrashN(_ note: Notification) { emitDrivingEvent("possibleCrash", note: note) }
|
|
707
|
+
|
|
708
|
+
@objc private func onPhoneUsageWhileDrivingN(_ note: Notification) {
|
|
709
|
+
if let loc = note.userInfo?["location"] as? MAURLocation,
|
|
710
|
+
let dict = loc.toDictionaryWithId() as? [String: Any] {
|
|
711
|
+
notifyListeners("phoneUsageWhileDriving", data: dict)
|
|
712
|
+
} else {
|
|
713
|
+
notifyListeners("phoneUsageWhileDriving", data: [:])
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// MARK: - Permission helper
|
|
719
|
+
|
|
720
|
+
/// Wraps `CLLocationManager` for a single permission prompt.
|
|
721
|
+
private final class PermissionRequestHelper: NSObject, CLLocationManagerDelegate {
|
|
722
|
+
private let manager = CLLocationManager()
|
|
723
|
+
private let completion: (CLAuthorizationStatus) -> Void
|
|
724
|
+
private var done = false
|
|
725
|
+
|
|
726
|
+
init(completion: @escaping (CLAuthorizationStatus) -> Void) {
|
|
727
|
+
self.completion = completion
|
|
728
|
+
super.init()
|
|
729
|
+
manager.delegate = self
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
func start() {
|
|
733
|
+
manager.requestWhenInUseAuthorization()
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
|
737
|
+
finish(with: manager.authorizationStatus)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// iOS 13 fallback (kept for SDK completeness; deployment target is 14+).
|
|
741
|
+
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
742
|
+
finish(with: status)
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
private func finish(with status: CLAuthorizationStatus) {
|
|
746
|
+
if status == .notDetermined || done { return }
|
|
747
|
+
done = true
|
|
748
|
+
completion(status)
|
|
749
|
+
}
|
|
750
|
+
}
|