@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,898 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 JosueLMM
|
|
3
|
+
//
|
|
4
|
+
// Capacitor 8+ bridge for the upstream `com.marianhello.bgloc` native core.
|
|
5
|
+
// The Cordova entry point (com.tenforwardconsulting.bgloc.cordova.BackgroundGeolocationPlugin)
|
|
6
|
+
// is the reference for behavior; this file mirrors its method set with Capacitor idioms.
|
|
7
|
+
|
|
8
|
+
package com.josuelmm.capacitor.backgroundgeolocation;
|
|
9
|
+
|
|
10
|
+
import android.Manifest;
|
|
11
|
+
import android.content.Context;
|
|
12
|
+
import android.content.pm.PackageManager;
|
|
13
|
+
import android.os.Build;
|
|
14
|
+
import android.os.PowerManager;
|
|
15
|
+
|
|
16
|
+
import com.getcapacitor.JSObject;
|
|
17
|
+
import com.getcapacitor.PermissionState;
|
|
18
|
+
import com.getcapacitor.Plugin;
|
|
19
|
+
import com.getcapacitor.PluginCall;
|
|
20
|
+
import com.getcapacitor.PluginMethod;
|
|
21
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
22
|
+
import com.getcapacitor.annotation.Permission;
|
|
23
|
+
import com.getcapacitor.annotation.PermissionCallback;
|
|
24
|
+
|
|
25
|
+
import com.marianhello.bgloc.BackgroundGeolocationFacade;
|
|
26
|
+
import com.marianhello.bgloc.Config;
|
|
27
|
+
import com.marianhello.bgloc.PluginDelegate;
|
|
28
|
+
import com.marianhello.bgloc.PluginException;
|
|
29
|
+
import com.marianhello.bgloc.data.BackgroundActivity;
|
|
30
|
+
import com.marianhello.bgloc.data.BackgroundLocation;
|
|
31
|
+
import com.marianhello.bgloc.oem.BatteryOemHelper;
|
|
32
|
+
import com.marianhello.logging.LogEntry;
|
|
33
|
+
import com.marianhello.logging.LoggerManager;
|
|
34
|
+
|
|
35
|
+
import org.json.JSONArray;
|
|
36
|
+
import org.json.JSONException;
|
|
37
|
+
import org.json.JSONObject;
|
|
38
|
+
|
|
39
|
+
import java.util.Collection;
|
|
40
|
+
import java.util.concurrent.atomic.AtomicInteger;
|
|
41
|
+
|
|
42
|
+
@CapacitorPlugin(
|
|
43
|
+
name = "BackgroundGeolocation",
|
|
44
|
+
permissions = {
|
|
45
|
+
@Permission(
|
|
46
|
+
alias = "location",
|
|
47
|
+
strings = {
|
|
48
|
+
Manifest.permission.ACCESS_FINE_LOCATION,
|
|
49
|
+
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
@Permission(
|
|
53
|
+
alias = "backgroundLocation",
|
|
54
|
+
strings = { "android.permission.ACCESS_BACKGROUND_LOCATION" }
|
|
55
|
+
),
|
|
56
|
+
@Permission(
|
|
57
|
+
alias = "activity",
|
|
58
|
+
strings = { "android.permission.ACTIVITY_RECOGNITION" }
|
|
59
|
+
),
|
|
60
|
+
@Permission(
|
|
61
|
+
alias = "notifications",
|
|
62
|
+
strings = { "android.permission.POST_NOTIFICATIONS" }
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
public class BackgroundGeolocationPlugin extends Plugin implements PluginDelegate {
|
|
67
|
+
|
|
68
|
+
private static final String LOCATION_EVENT = "location";
|
|
69
|
+
private static final String STATIONARY_EVENT = "stationary";
|
|
70
|
+
private static final String ACTIVITY_EVENT = "activity";
|
|
71
|
+
private static final String FOREGROUND_EVENT = "foreground";
|
|
72
|
+
private static final String BACKGROUND_EVENT = "background";
|
|
73
|
+
private static final String AUTHORIZATION_EVENT = "authorization";
|
|
74
|
+
private static final String START_EVENT = "start";
|
|
75
|
+
private static final String STOP_EVENT = "stop";
|
|
76
|
+
private static final String ABORT_REQUESTED_EVENT = "abort_requested";
|
|
77
|
+
private static final String HTTP_AUTHORIZATION_EVENT = "http_authorization";
|
|
78
|
+
private static final String ERROR_EVENT = "error";
|
|
79
|
+
|
|
80
|
+
public static final String PLUGIN_VERSION = "1.0.0";
|
|
81
|
+
|
|
82
|
+
private BackgroundGeolocationFacade facade;
|
|
83
|
+
private org.slf4j.Logger logger;
|
|
84
|
+
private final AtomicInteger taskCounter = new AtomicInteger(0);
|
|
85
|
+
|
|
86
|
+
@Override
|
|
87
|
+
public void load() {
|
|
88
|
+
super.load();
|
|
89
|
+
logger = LoggerManager.getLogger(BackgroundGeolocationPlugin.class);
|
|
90
|
+
facade = new BackgroundGeolocationFacade(getAppContext(), this);
|
|
91
|
+
facade.resume();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Override
|
|
95
|
+
protected void handleOnPause() {
|
|
96
|
+
if (facade != null) facade.pause();
|
|
97
|
+
notifyListeners(BACKGROUND_EVENT, new JSObject());
|
|
98
|
+
super.handleOnPause();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Override
|
|
102
|
+
protected void handleOnResume() {
|
|
103
|
+
if (facade != null) facade.resume();
|
|
104
|
+
notifyListeners(FOREGROUND_EVENT, new JSObject());
|
|
105
|
+
super.handleOnResume();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Override
|
|
109
|
+
protected void handleOnDestroy() {
|
|
110
|
+
if (facade != null) facade.destroy();
|
|
111
|
+
super.handleOnDestroy();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private Context getAppContext() {
|
|
115
|
+
return getBridge().getActivity().getApplicationContext();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private void rejectWith(PluginCall call, String message, Exception cause, int code) {
|
|
119
|
+
JSObject details = new JSObject();
|
|
120
|
+
details.put("code", code);
|
|
121
|
+
if (cause != null && cause.getMessage() != null) {
|
|
122
|
+
details.put("cause", cause.getMessage());
|
|
123
|
+
}
|
|
124
|
+
call.reject(message, String.valueOf(code), cause, details);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private void rejectWith(PluginCall call, PluginException e) {
|
|
128
|
+
JSObject details = new JSObject();
|
|
129
|
+
details.put("code", e.getCode());
|
|
130
|
+
call.reject(e.getMessage() != null ? e.getMessage() : "Plugin error",
|
|
131
|
+
String.valueOf(e.getCode()), e, details);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@PluginMethod
|
|
135
|
+
public void configure(PluginCall call) {
|
|
136
|
+
try {
|
|
137
|
+
JSObject data = call.getData();
|
|
138
|
+
Config config = ConfigMapper.fromJSONObject(data);
|
|
139
|
+
facade.configure(config);
|
|
140
|
+
call.resolve();
|
|
141
|
+
} catch (JSONException e) {
|
|
142
|
+
rejectWith(call, "Configuration error", e, PluginException.JSON_ERROR);
|
|
143
|
+
} catch (PluginException e) {
|
|
144
|
+
rejectWith(call, e);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@PluginMethod
|
|
149
|
+
public void start(PluginCall call) {
|
|
150
|
+
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
151
|
+
requestPermissionForAlias("location", call, "startAfterPermission");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
facade.start();
|
|
155
|
+
call.resolve();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@PermissionCallback
|
|
159
|
+
private void startAfterPermission(PluginCall call) {
|
|
160
|
+
if (getPermissionState("location") != PermissionState.GRANTED) {
|
|
161
|
+
rejectWith(call, "Location permission denied", null, PluginException.PERMISSION_DENIED_ERROR);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
facade.start();
|
|
165
|
+
call.resolve();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@PluginMethod
|
|
169
|
+
public void stop(PluginCall call) {
|
|
170
|
+
facade.stop();
|
|
171
|
+
call.resolve();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@PluginMethod
|
|
175
|
+
public void getCurrentLocation(PluginCall call) {
|
|
176
|
+
int timeout = call.getInt("timeout", Integer.MAX_VALUE);
|
|
177
|
+
long maximumAge = call.getLong("maximumAge", Long.MAX_VALUE);
|
|
178
|
+
boolean enableHighAccuracy = Boolean.TRUE.equals(call.getBoolean("enableHighAccuracy", false));
|
|
179
|
+
try {
|
|
180
|
+
BackgroundLocation location = facade.getCurrentLocation(timeout, maximumAge, enableHighAccuracy);
|
|
181
|
+
call.resolve(JSObject.fromJSONObject(location.toJSONObject()));
|
|
182
|
+
} catch (JSONException e) {
|
|
183
|
+
rejectWith(call, "Error serializing location", e, PluginException.JSON_ERROR);
|
|
184
|
+
} catch (PluginException e) {
|
|
185
|
+
rejectWith(call, e);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@PluginMethod
|
|
190
|
+
public void getStationaryLocation(PluginCall call) {
|
|
191
|
+
try {
|
|
192
|
+
BackgroundLocation stationary = facade.getStationaryLocation();
|
|
193
|
+
if (stationary != null) {
|
|
194
|
+
call.resolve(JSObject.fromJSONObject(stationary.toJSONObject()));
|
|
195
|
+
} else {
|
|
196
|
+
call.resolve();
|
|
197
|
+
}
|
|
198
|
+
} catch (JSONException e) {
|
|
199
|
+
rejectWith(call, "Getting stationary location failed", e, PluginException.JSON_ERROR);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@PluginMethod
|
|
204
|
+
public void getLocations(PluginCall call) {
|
|
205
|
+
try {
|
|
206
|
+
JSObject ret = new JSObject();
|
|
207
|
+
ret.put("locations", locationsToJsonArray(facade.getLocations()));
|
|
208
|
+
call.resolve(ret);
|
|
209
|
+
} catch (JSONException e) {
|
|
210
|
+
rejectWith(call, "Converting locations to JSON failed", e, PluginException.JSON_ERROR);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@PluginMethod
|
|
215
|
+
public void getValidLocations(PluginCall call) {
|
|
216
|
+
try {
|
|
217
|
+
JSObject ret = new JSObject();
|
|
218
|
+
ret.put("locations", locationsToJsonArray(facade.getValidLocations()));
|
|
219
|
+
call.resolve(ret);
|
|
220
|
+
} catch (JSONException e) {
|
|
221
|
+
rejectWith(call, "Converting locations to JSON failed", e, PluginException.JSON_ERROR);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@PluginMethod
|
|
226
|
+
public void getValidLocationsAndDelete(PluginCall call) {
|
|
227
|
+
try {
|
|
228
|
+
JSObject ret = new JSObject();
|
|
229
|
+
ret.put("locations", locationsToJsonArray(facade.getValidLocationsAndDelete()));
|
|
230
|
+
call.resolve(ret);
|
|
231
|
+
} catch (JSONException e) {
|
|
232
|
+
rejectWith(call, "Converting locations to JSON failed", e, PluginException.JSON_ERROR);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@PluginMethod
|
|
237
|
+
public void getConfig(PluginCall call) {
|
|
238
|
+
try {
|
|
239
|
+
Config config = facade.getConfig();
|
|
240
|
+
call.resolve(ConfigMapper.toJSObject(config));
|
|
241
|
+
} catch (JSONException e) {
|
|
242
|
+
rejectWith(call, "Error getting config", e, PluginException.JSON_ERROR);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@PluginMethod
|
|
247
|
+
public void deleteLocation(PluginCall call) {
|
|
248
|
+
Long locationId = call.getLong("locationId");
|
|
249
|
+
if (locationId == null) {
|
|
250
|
+
rejectWith(call, "locationId is required", null, PluginException.JSON_ERROR);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
facade.deleteLocation(locationId);
|
|
254
|
+
call.resolve();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@PluginMethod
|
|
258
|
+
public void deleteAllLocations(PluginCall call) {
|
|
259
|
+
facade.deleteAllLocations();
|
|
260
|
+
call.resolve();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@PluginMethod
|
|
264
|
+
public void isLocationEnabled(PluginCall call) {
|
|
265
|
+
try {
|
|
266
|
+
JSObject ret = new JSObject();
|
|
267
|
+
ret.put("enabled", facade.locationServicesEnabled());
|
|
268
|
+
call.resolve(ret);
|
|
269
|
+
} catch (PluginException e) {
|
|
270
|
+
rejectWith(call, e);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@PluginMethod
|
|
275
|
+
public void showAppSettings(PluginCall call) {
|
|
276
|
+
BackgroundGeolocationFacade.showAppSettings(getAppContext());
|
|
277
|
+
call.resolve();
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@PluginMethod
|
|
281
|
+
public void openSettings(PluginCall call) {
|
|
282
|
+
BackgroundGeolocationFacade.showAppSettings(getAppContext());
|
|
283
|
+
call.resolve();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
@PluginMethod
|
|
287
|
+
public void showLocationSettings(PluginCall call) {
|
|
288
|
+
BackgroundGeolocationFacade.showLocationSettings(getAppContext());
|
|
289
|
+
call.resolve();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@PluginMethod
|
|
293
|
+
public void watchLocationMode(PluginCall call) {
|
|
294
|
+
call.resolve();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@PluginMethod
|
|
298
|
+
public void stopWatchingLocationMode(PluginCall call) {
|
|
299
|
+
call.resolve();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@PluginMethod
|
|
303
|
+
public void getLogEntries(PluginCall call) {
|
|
304
|
+
try {
|
|
305
|
+
int limit = call.getInt("limit", 100);
|
|
306
|
+
int offset = call.getInt("fromId", 0);
|
|
307
|
+
String minLevel = call.getString("minLevel", "DEBUG");
|
|
308
|
+
JSObject ret = new JSObject();
|
|
309
|
+
ret.put("entries", logsToJsonArray(limit, offset, minLevel));
|
|
310
|
+
call.resolve(ret);
|
|
311
|
+
} catch (Exception e) {
|
|
312
|
+
rejectWith(call, "Getting logs failed", e, PluginException.SERVICE_ERROR);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@PluginMethod
|
|
317
|
+
public void checkStatus(PluginCall call) {
|
|
318
|
+
try {
|
|
319
|
+
JSObject ret = new JSObject();
|
|
320
|
+
ret.put("isRunning", facade.isRunning());
|
|
321
|
+
ret.put("locationServicesEnabled", facade.locationServicesEnabled());
|
|
322
|
+
ret.put("authorization", facade.getAuthorizationStatus());
|
|
323
|
+
ret.put("hasPermissions", facade.hasPermissions());
|
|
324
|
+
call.resolve(ret);
|
|
325
|
+
} catch (PluginException e) {
|
|
326
|
+
rejectWith(call, e);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@PluginMethod
|
|
331
|
+
public void startTask(PluginCall call) {
|
|
332
|
+
JSObject ret = new JSObject();
|
|
333
|
+
ret.put("taskKey", taskCounter.incrementAndGet());
|
|
334
|
+
call.resolve(ret);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
@PluginMethod
|
|
338
|
+
public void endTask(PluginCall call) {
|
|
339
|
+
call.resolve();
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
@PluginMethod
|
|
343
|
+
public void forceSync(PluginCall call) {
|
|
344
|
+
facade.forceSync();
|
|
345
|
+
call.resolve();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
@PluginMethod
|
|
349
|
+
public void clearSync(PluginCall call) {
|
|
350
|
+
facade.clearSync();
|
|
351
|
+
call.resolve();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
@PluginMethod
|
|
355
|
+
public void getPendingSyncCount(PluginCall call) {
|
|
356
|
+
try {
|
|
357
|
+
long count = facade.getPendingSyncCount();
|
|
358
|
+
JSObject ret = new JSObject();
|
|
359
|
+
ret.put("count", (int) Math.min(count, Integer.MAX_VALUE));
|
|
360
|
+
call.resolve(ret);
|
|
361
|
+
} catch (Exception e) {
|
|
362
|
+
rejectWith(call, "getPendingSyncCount failed", e, PluginException.SERVICE_ERROR);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@PluginMethod
|
|
367
|
+
public void switchMode(PluginCall call) {
|
|
368
|
+
Integer mode = call.getInt("mode");
|
|
369
|
+
if (mode == null) {
|
|
370
|
+
rejectWith(call, "mode is required", null, PluginException.JSON_ERROR);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
facade.switchMode(mode);
|
|
374
|
+
call.resolve();
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@PluginMethod
|
|
378
|
+
public void startSession(PluginCall call) {
|
|
379
|
+
facade.startSession();
|
|
380
|
+
call.resolve();
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@PluginMethod
|
|
384
|
+
public void clearSession(PluginCall call) {
|
|
385
|
+
facade.clearSession();
|
|
386
|
+
call.resolve();
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@PluginMethod
|
|
390
|
+
public void getSessionLocations(PluginCall call) {
|
|
391
|
+
try {
|
|
392
|
+
JSObject ret = new JSObject();
|
|
393
|
+
ret.put("locations", locationsToJsonArray(facade.getSessionLocations()));
|
|
394
|
+
call.resolve(ret);
|
|
395
|
+
} catch (JSONException e) {
|
|
396
|
+
rejectWith(call, "getSessionLocations failed", e, PluginException.JSON_ERROR);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
@PluginMethod
|
|
401
|
+
public void getSessionLocationsCount(PluginCall call) {
|
|
402
|
+
try {
|
|
403
|
+
int count = facade.getSessionLocationsCount();
|
|
404
|
+
JSObject ret = new JSObject();
|
|
405
|
+
ret.put("count", count);
|
|
406
|
+
call.resolve(ret);
|
|
407
|
+
} catch (Exception e) {
|
|
408
|
+
rejectWith(call, "getSessionLocationsCount failed", e, PluginException.SERVICE_ERROR);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
@PluginMethod
|
|
413
|
+
public void getPluginVersion(PluginCall call) {
|
|
414
|
+
JSObject ret = new JSObject();
|
|
415
|
+
ret.put("version", PLUGIN_VERSION);
|
|
416
|
+
call.resolve(ret);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
@PluginMethod
|
|
420
|
+
public void getDiagnostics(PluginCall call) {
|
|
421
|
+
try {
|
|
422
|
+
Context ctx = getAppContext();
|
|
423
|
+
JSObject d = new JSObject();
|
|
424
|
+
d.put("isRunning", facade.isRunning());
|
|
425
|
+
try {
|
|
426
|
+
d.put("locationServicesEnabled", facade.locationServicesEnabled());
|
|
427
|
+
} catch (PluginException e) {
|
|
428
|
+
d.put("locationServicesEnabled", JSONObject.NULL);
|
|
429
|
+
}
|
|
430
|
+
try {
|
|
431
|
+
Config cfg = facade.getConfig();
|
|
432
|
+
if (cfg != null) {
|
|
433
|
+
d.put("startOnBoot", cfg.getStartOnBoot());
|
|
434
|
+
}
|
|
435
|
+
} catch (Exception ignored) {}
|
|
436
|
+
try {
|
|
437
|
+
d.put("pendingSyncCount", (int) Math.min(facade.getPendingSyncCount(), Integer.MAX_VALUE));
|
|
438
|
+
} catch (Exception ignored) {}
|
|
439
|
+
try {
|
|
440
|
+
BackgroundLocation last = facade.getStationaryLocation();
|
|
441
|
+
d.put("lastLocationAt", last != null ? last.getTime() : JSONObject.NULL);
|
|
442
|
+
} catch (Exception e) {
|
|
443
|
+
d.put("lastLocationAt", JSONObject.NULL);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
d.put("fineLocationGranted", hasPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION));
|
|
447
|
+
d.put("coarseLocationGranted", hasPermission(ctx, Manifest.permission.ACCESS_COARSE_LOCATION));
|
|
448
|
+
if (Build.VERSION.SDK_INT >= 29) {
|
|
449
|
+
d.put("backgroundLocationGranted", hasPermission(ctx, "android.permission.ACCESS_BACKGROUND_LOCATION"));
|
|
450
|
+
d.put("activityRecognitionGranted", hasPermission(ctx, "android.permission.ACTIVITY_RECOGNITION"));
|
|
451
|
+
} else {
|
|
452
|
+
d.put("backgroundLocationGranted", true);
|
|
453
|
+
d.put("activityRecognitionGranted", true);
|
|
454
|
+
}
|
|
455
|
+
if (Build.VERSION.SDK_INT >= 33) {
|
|
456
|
+
d.put("notificationPermissionGranted", hasPermission(ctx, "android.permission.POST_NOTIFICATIONS"));
|
|
457
|
+
} else {
|
|
458
|
+
d.put("notificationPermissionGranted", true);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
d.put("batteryOptimizationIgnored", isIgnoringBatteryOptimizations(ctx));
|
|
462
|
+
d.put("manufacturer", Build.MANUFACTURER != null ? Build.MANUFACTURER : "");
|
|
463
|
+
d.put("foregroundServiceType", readForegroundServiceTypeFromManifest(ctx));
|
|
464
|
+
|
|
465
|
+
call.resolve(d);
|
|
466
|
+
} catch (Exception e) {
|
|
467
|
+
rejectWith(call, "getDiagnostics failed", e, PluginException.SERVICE_ERROR);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
@PluginMethod
|
|
472
|
+
public void isIgnoringBatteryOptimizations(PluginCall call) {
|
|
473
|
+
JSObject ret = new JSObject();
|
|
474
|
+
ret.put("whitelisted", BatteryOemHelper.isIgnoringBatteryOptimizations(getAppContext()));
|
|
475
|
+
call.resolve(ret);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
@PluginMethod
|
|
479
|
+
public void requestIgnoreBatteryOptimizations(PluginCall call) {
|
|
480
|
+
try {
|
|
481
|
+
BatteryOemHelper.requestIgnoreBatteryOptimizations(getActivity());
|
|
482
|
+
} catch (Exception ignored) {}
|
|
483
|
+
JSObject ret = new JSObject();
|
|
484
|
+
ret.put("whitelisted", BatteryOemHelper.isIgnoringBatteryOptimizations(getAppContext()));
|
|
485
|
+
call.resolve(ret);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
@PluginMethod
|
|
489
|
+
public void openBatterySettings(PluginCall call) {
|
|
490
|
+
try {
|
|
491
|
+
BatteryOemHelper.openBatterySettings(getActivity());
|
|
492
|
+
} catch (Exception ignored) {}
|
|
493
|
+
call.resolve();
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
@PluginMethod
|
|
497
|
+
public void openAutoStartSettings(PluginCall call) {
|
|
498
|
+
try {
|
|
499
|
+
JSONObject result = BatteryOemHelper.openAutoStartSettings(getActivity());
|
|
500
|
+
call.resolve(JSObject.fromJSONObject(result));
|
|
501
|
+
} catch (Exception e) {
|
|
502
|
+
rejectWith(call, "openAutoStartSettings failed", e, PluginException.SERVICE_ERROR);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
@PluginMethod
|
|
507
|
+
public void getManufacturerHelp(PluginCall call) {
|
|
508
|
+
try {
|
|
509
|
+
JSONObject result = BatteryOemHelper.getManufacturerHelp();
|
|
510
|
+
call.resolve(JSObject.fromJSONObject(result));
|
|
511
|
+
} catch (Exception e) {
|
|
512
|
+
rejectWith(call, "getManufacturerHelp failed", e, PluginException.SERVICE_ERROR);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
@PluginMethod
|
|
517
|
+
public void triggerSOS(PluginCall call) {
|
|
518
|
+
try {
|
|
519
|
+
JSObject payload = call.getObject("payload");
|
|
520
|
+
facade.triggerSOS(payload);
|
|
521
|
+
call.resolve();
|
|
522
|
+
} catch (Exception e) {
|
|
523
|
+
rejectWith(call, "triggerSOS failed", e, PluginException.SERVICE_ERROR);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
@PluginMethod
|
|
528
|
+
public void requestBackgroundLocationPermission(PluginCall call) {
|
|
529
|
+
if (Build.VERSION.SDK_INT < 29) {
|
|
530
|
+
JSObject ret = new JSObject();
|
|
531
|
+
ret.put("granted", true);
|
|
532
|
+
ret.put("notRequired", true);
|
|
533
|
+
call.resolve(ret);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (getPermissionState("backgroundLocation") == PermissionState.GRANTED) {
|
|
537
|
+
JSObject ret = new JSObject();
|
|
538
|
+
ret.put("granted", true);
|
|
539
|
+
call.resolve(ret);
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
requestPermissionForAlias("backgroundLocation", call, "backgroundLocationPermissionCallback");
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
@PermissionCallback
|
|
546
|
+
private void backgroundLocationPermissionCallback(PluginCall call) {
|
|
547
|
+
boolean granted = getPermissionState("backgroundLocation") == PermissionState.GRANTED;
|
|
548
|
+
JSObject ret = new JSObject();
|
|
549
|
+
ret.put("granted", granted);
|
|
550
|
+
if (!granted) {
|
|
551
|
+
JSONArray denied = new JSONArray();
|
|
552
|
+
denied.put("android.permission.ACCESS_BACKGROUND_LOCATION");
|
|
553
|
+
ret.put("denied", denied);
|
|
554
|
+
}
|
|
555
|
+
call.resolve(ret);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
@PluginMethod
|
|
559
|
+
public void requestActivityRecognitionPermission(PluginCall call) {
|
|
560
|
+
if (Build.VERSION.SDK_INT < 29) {
|
|
561
|
+
JSObject ret = new JSObject();
|
|
562
|
+
ret.put("granted", true);
|
|
563
|
+
ret.put("notRequired", true);
|
|
564
|
+
call.resolve(ret);
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
if (getPermissionState("activity") == PermissionState.GRANTED) {
|
|
568
|
+
JSObject ret = new JSObject();
|
|
569
|
+
ret.put("granted", true);
|
|
570
|
+
call.resolve(ret);
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
requestPermissionForAlias("activity", call, "activityPermissionCallback");
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
@PermissionCallback
|
|
577
|
+
private void activityPermissionCallback(PluginCall call) {
|
|
578
|
+
boolean granted = getPermissionState("activity") == PermissionState.GRANTED;
|
|
579
|
+
JSObject ret = new JSObject();
|
|
580
|
+
ret.put("granted", granted);
|
|
581
|
+
if (!granted) {
|
|
582
|
+
JSONArray denied = new JSONArray();
|
|
583
|
+
denied.put("android.permission.ACTIVITY_RECOGNITION");
|
|
584
|
+
ret.put("denied", denied);
|
|
585
|
+
}
|
|
586
|
+
call.resolve(ret);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
@PluginMethod
|
|
590
|
+
public void requestNotificationPermission(PluginCall call) {
|
|
591
|
+
if (Build.VERSION.SDK_INT < 33) {
|
|
592
|
+
JSObject ret = new JSObject();
|
|
593
|
+
ret.put("granted", true);
|
|
594
|
+
ret.put("notRequired", true);
|
|
595
|
+
call.resolve(ret);
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
if (getPermissionState("notifications") == PermissionState.GRANTED) {
|
|
599
|
+
JSObject ret = new JSObject();
|
|
600
|
+
ret.put("granted", true);
|
|
601
|
+
call.resolve(ret);
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
requestPermissionForAlias("notifications", call, "notificationsPermissionCallback");
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
@PermissionCallback
|
|
608
|
+
private void notificationsPermissionCallback(PluginCall call) {
|
|
609
|
+
boolean granted = getPermissionState("notifications") == PermissionState.GRANTED;
|
|
610
|
+
JSObject ret = new JSObject();
|
|
611
|
+
ret.put("granted", granted);
|
|
612
|
+
if (!granted) {
|
|
613
|
+
JSONArray denied = new JSONArray();
|
|
614
|
+
denied.put("android.permission.POST_NOTIFICATIONS");
|
|
615
|
+
ret.put("denied", denied);
|
|
616
|
+
}
|
|
617
|
+
call.resolve(ret);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
@PluginMethod
|
|
621
|
+
public void registerHeadlessTask(PluginCall call) {
|
|
622
|
+
String taskJs = call.getString("task");
|
|
623
|
+
if (taskJs == null || taskJs.length() == 0) {
|
|
624
|
+
rejectWith(call, "task body is required", null, PluginException.JSON_ERROR);
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
HeadlessTaskRegistry.getInstance().registerHeadlessTask(taskJs);
|
|
628
|
+
facade.registerHeadlessTask(JsEvaluatorTaskRunner.class.getName());
|
|
629
|
+
call.resolve();
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
@Override
|
|
633
|
+
@PluginMethod
|
|
634
|
+
public void removeAllListeners(PluginCall call) {
|
|
635
|
+
super.removeAllListeners(call);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
@Override
|
|
639
|
+
public void onAuthorizationChanged(int authStatus) {
|
|
640
|
+
JSObject payload = new JSObject();
|
|
641
|
+
payload.put("status", authStatus);
|
|
642
|
+
notifyListeners(AUTHORIZATION_EVENT, payload);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
@Override
|
|
646
|
+
public void onLocationChanged(BackgroundLocation location) {
|
|
647
|
+
try {
|
|
648
|
+
notifyListeners(LOCATION_EVENT, JSObject.fromJSONObject(location.toJSONObjectWithId()));
|
|
649
|
+
} catch (JSONException e) {
|
|
650
|
+
emitError(new PluginException(e.getMessage(), PluginException.JSON_ERROR));
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
@Override
|
|
655
|
+
public void onStationaryChanged(BackgroundLocation location) {
|
|
656
|
+
try {
|
|
657
|
+
notifyListeners(STATIONARY_EVENT, JSObject.fromJSONObject(location.toJSONObjectWithId()));
|
|
658
|
+
} catch (JSONException e) {
|
|
659
|
+
emitError(new PluginException(e.getMessage(), PluginException.JSON_ERROR));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
@Override
|
|
664
|
+
public void onActivityChanged(BackgroundActivity activity) {
|
|
665
|
+
try {
|
|
666
|
+
notifyListeners(ACTIVITY_EVENT, JSObject.fromJSONObject(activity.toJSONObject()));
|
|
667
|
+
} catch (JSONException e) {
|
|
668
|
+
emitError(new PluginException(e.getMessage(), PluginException.JSON_ERROR));
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
@Override
|
|
673
|
+
public void onServiceStatusChanged(int status) {
|
|
674
|
+
switch (status) {
|
|
675
|
+
case BackgroundGeolocationFacade.SERVICE_STARTED:
|
|
676
|
+
notifyListeners(START_EVENT, new JSObject());
|
|
677
|
+
return;
|
|
678
|
+
case BackgroundGeolocationFacade.SERVICE_STOPPED:
|
|
679
|
+
notifyListeners(STOP_EVENT, new JSObject());
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
@Override
|
|
685
|
+
public void onAbortRequested() {
|
|
686
|
+
notifyListeners(ABORT_REQUESTED_EVENT, new JSObject());
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
@Override
|
|
690
|
+
public void onHttpAuthorization() {
|
|
691
|
+
notifyListeners(HTTP_AUTHORIZATION_EVENT, new JSObject());
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
@Override
|
|
695
|
+
public void onError(PluginException e) {
|
|
696
|
+
emitError(e);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// v3.5 Phase 4 — sync queue events
|
|
700
|
+
@Override
|
|
701
|
+
public void onSyncStart() {
|
|
702
|
+
notifyListeners("syncStart", new JSObject());
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
@Override
|
|
706
|
+
public void onSyncSuccess(int locationsSent) {
|
|
707
|
+
JSObject p = new JSObject();
|
|
708
|
+
p.put("sent", locationsSent);
|
|
709
|
+
notifyListeners("syncSuccess", p);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
@Override
|
|
713
|
+
public void onSyncError(int httpStatus, String message) {
|
|
714
|
+
JSObject p = new JSObject();
|
|
715
|
+
p.put("httpStatus", httpStatus);
|
|
716
|
+
p.put("message", message != null ? message : "");
|
|
717
|
+
notifyListeners("syncError", p);
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
@Override
|
|
721
|
+
public void onSyncProgress(int progress) {
|
|
722
|
+
JSObject p = new JSObject();
|
|
723
|
+
p.put("progress", progress);
|
|
724
|
+
notifyListeners("syncProgress", p);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
@Override
|
|
728
|
+
public void onHeartbeat(BackgroundLocation location) {
|
|
729
|
+
notifyListeners("heartbeat", locationToJSObject(location));
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// v4.0 Phase 6 — driver-insight events
|
|
733
|
+
@Override
|
|
734
|
+
public void onTripStart(BackgroundLocation location) {
|
|
735
|
+
notifyListeners("tripStart", locationToJSObject(location));
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
@Override
|
|
739
|
+
public void onTripEnd(BackgroundLocation location, double distance, long durationMs) {
|
|
740
|
+
JSObject p = new JSObject();
|
|
741
|
+
p.put("location", locationJsonOrNull(location));
|
|
742
|
+
p.put("distance", distance);
|
|
743
|
+
p.put("durationMs", durationMs);
|
|
744
|
+
notifyListeners("tripEnd", p);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
@Override
|
|
748
|
+
public void onMoving(BackgroundLocation location) {
|
|
749
|
+
notifyListeners("moving", locationToJSObject(location));
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
@Override
|
|
753
|
+
public void onStopped(BackgroundLocation location) {
|
|
754
|
+
notifyListeners("stopped", locationToJSObject(location));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
@Override
|
|
758
|
+
public void onSpeeding(BackgroundLocation location, double speedKmh, double limitKmh) {
|
|
759
|
+
JSObject p = new JSObject();
|
|
760
|
+
p.put("location", locationJsonOrNull(location));
|
|
761
|
+
p.put("speedKmh", speedKmh);
|
|
762
|
+
p.put("limitKmh", limitKmh);
|
|
763
|
+
notifyListeners("speeding", p);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
@Override
|
|
767
|
+
public void onProviderChange(String provider) {
|
|
768
|
+
JSObject p = new JSObject();
|
|
769
|
+
p.put("provider", provider != null ? provider : "");
|
|
770
|
+
notifyListeners("providerChange", p);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
@Override
|
|
774
|
+
public void onSOS(BackgroundLocation location, JSONObject userPayload) {
|
|
775
|
+
try {
|
|
776
|
+
JSObject p = userPayload != null ? JSObject.fromJSONObject(userPayload) : new JSObject();
|
|
777
|
+
p.put("location", locationJsonOrNull(location));
|
|
778
|
+
notifyListeners("sos", p);
|
|
779
|
+
} catch (JSONException e) {
|
|
780
|
+
JSObject p = new JSObject();
|
|
781
|
+
p.put("location", locationJsonOrNull(location));
|
|
782
|
+
notifyListeners("sos", p);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// v4.1 GPS-derived sensor-like events
|
|
787
|
+
@Override
|
|
788
|
+
public void onHardBrake(BackgroundLocation location, double decelMps2) {
|
|
789
|
+
emitDrivingEvent("hardBrake", location, decelMps2);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
@Override
|
|
793
|
+
public void onRapidAcceleration(BackgroundLocation location, double accelMps2) {
|
|
794
|
+
emitDrivingEvent("rapidAcceleration", location, accelMps2);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
@Override
|
|
798
|
+
public void onSharpTurn(BackgroundLocation location, double degPerSec) {
|
|
799
|
+
emitDrivingEvent("sharpTurn", location, degPerSec);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
@Override
|
|
803
|
+
public void onPossibleCrash(BackgroundLocation location, double value, String source) {
|
|
804
|
+
JSObject p = new JSObject();
|
|
805
|
+
p.put("location", locationJsonOrNull(location));
|
|
806
|
+
p.put("value", value);
|
|
807
|
+
p.put("source", source != null ? source : "gps");
|
|
808
|
+
notifyListeners("possibleCrash", p);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
@Override
|
|
812
|
+
public void onPhoneUsageWhileDriving(BackgroundLocation location) {
|
|
813
|
+
notifyListeners("phoneUsageWhileDriving", locationToJSObject(location));
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
private void emitDrivingEvent(String name, BackgroundLocation location, double value) {
|
|
817
|
+
JSObject p = new JSObject();
|
|
818
|
+
p.put("location", locationJsonOrNull(location));
|
|
819
|
+
p.put("value", value);
|
|
820
|
+
notifyListeners(name, p);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
private void emitError(PluginException e) {
|
|
824
|
+
JSObject payload = new JSObject();
|
|
825
|
+
payload.put("code", e.getCode());
|
|
826
|
+
payload.put("message", e.getMessage());
|
|
827
|
+
notifyListeners(ERROR_EVENT, payload);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private static JSONArray locationsToJsonArray(Collection<BackgroundLocation> locations) throws JSONException {
|
|
831
|
+
JSONArray arr = new JSONArray();
|
|
832
|
+
for (BackgroundLocation location : locations) {
|
|
833
|
+
arr.put(location.toJSONObjectWithId());
|
|
834
|
+
}
|
|
835
|
+
return arr;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
private JSONArray logsToJsonArray(int limit, int offset, String minLevel) throws Exception {
|
|
839
|
+
JSONArray arr = new JSONArray();
|
|
840
|
+
Collection<LogEntry> entries = facade.getLogEntries(limit, offset, minLevel);
|
|
841
|
+
for (LogEntry entry : entries) {
|
|
842
|
+
arr.put(entry.toJSONObject());
|
|
843
|
+
}
|
|
844
|
+
return arr;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
private static JSObject locationToJSObject(BackgroundLocation location) {
|
|
848
|
+
if (location == null) return new JSObject();
|
|
849
|
+
try {
|
|
850
|
+
return JSObject.fromJSONObject(location.toJSONObjectWithId());
|
|
851
|
+
} catch (JSONException e) {
|
|
852
|
+
return new JSObject();
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
private static Object locationJsonOrNull(BackgroundLocation location) {
|
|
857
|
+
if (location == null) return JSONObject.NULL;
|
|
858
|
+
try {
|
|
859
|
+
return location.toJSONObjectWithId();
|
|
860
|
+
} catch (JSONException e) {
|
|
861
|
+
return JSONObject.NULL;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
private static boolean hasPermission(Context ctx, String permission) {
|
|
866
|
+
try {
|
|
867
|
+
return ctx.getPackageManager().checkPermission(permission, ctx.getPackageName())
|
|
868
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
869
|
+
} catch (Exception e) {
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
private static boolean isIgnoringBatteryOptimizations(Context ctx) {
|
|
875
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
|
|
876
|
+
try {
|
|
877
|
+
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
|
|
878
|
+
return pm != null && pm.isIgnoringBatteryOptimizations(ctx.getPackageName());
|
|
879
|
+
} catch (Exception e) {
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
private static int readForegroundServiceTypeFromManifest(Context ctx) {
|
|
885
|
+
if (Build.VERSION.SDK_INT < 34) return 0;
|
|
886
|
+
try {
|
|
887
|
+
android.content.ComponentName cn = new android.content.ComponentName(
|
|
888
|
+
ctx, com.marianhello.bgloc.service.LocationServiceImpl.class);
|
|
889
|
+
android.content.pm.ServiceInfo si = ctx.getPackageManager().getServiceInfo(
|
|
890
|
+
cn, android.content.pm.PackageManager.ComponentInfoFlags.of(0));
|
|
891
|
+
java.lang.reflect.Field f = android.content.pm.ServiceInfo.class.getField("foregroundServiceType");
|
|
892
|
+
Object v = f.get(si);
|
|
893
|
+
return (v instanceof Integer) ? (Integer) v : 0;
|
|
894
|
+
} catch (Throwable e) {
|
|
895
|
+
return 0;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|