@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,301 @@
|
|
|
1
|
+
package com.marianhello.bgloc.sync;
|
|
2
|
+
|
|
3
|
+
import android.accounts.Account;
|
|
4
|
+
import android.app.NotificationManager;
|
|
5
|
+
import android.content.AbstractThreadedSyncAdapter;
|
|
6
|
+
import android.content.ContentProviderClient;
|
|
7
|
+
import android.content.ContentResolver;
|
|
8
|
+
import android.content.Context;
|
|
9
|
+
import android.content.Intent;
|
|
10
|
+
import android.content.SyncResult;
|
|
11
|
+
import android.os.Bundle;
|
|
12
|
+
import android.os.Handler;
|
|
13
|
+
import android.os.Looper;
|
|
14
|
+
import androidx.core.app.NotificationCompat;
|
|
15
|
+
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
|
16
|
+
|
|
17
|
+
import com.marianhello.bgloc.Config;
|
|
18
|
+
import com.marianhello.bgloc.HttpPostService;
|
|
19
|
+
import com.marianhello.bgloc.data.ConfigurationDAO;
|
|
20
|
+
import com.marianhello.bgloc.data.DAOFactory;
|
|
21
|
+
import com.marianhello.bgloc.service.LocationServiceImpl;
|
|
22
|
+
import com.marianhello.logging.LoggerManager;
|
|
23
|
+
|
|
24
|
+
import org.json.JSONException;
|
|
25
|
+
|
|
26
|
+
import java.io.File;
|
|
27
|
+
import java.io.IOException;
|
|
28
|
+
import java.util.HashMap;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Handle the transfer of data between a server and an
|
|
32
|
+
* app, using the Android sync adapter framework.
|
|
33
|
+
*/
|
|
34
|
+
public class SyncAdapter extends AbstractThreadedSyncAdapter implements HttpPostService.UploadingProgressListener {
|
|
35
|
+
|
|
36
|
+
private static final int NOTIFICATION_ID = 666;
|
|
37
|
+
|
|
38
|
+
ContentResolver contentResolver;
|
|
39
|
+
private ConfigurationDAO configDAO;
|
|
40
|
+
private NotificationManager notificationManager;
|
|
41
|
+
private BatchManager batchManager;
|
|
42
|
+
private boolean notificationsEnabled = true;
|
|
43
|
+
private volatile Config currentSyncConfig;
|
|
44
|
+
|
|
45
|
+
private org.slf4j.Logger logger;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Set up the sync adapter
|
|
49
|
+
*/
|
|
50
|
+
public SyncAdapter(Context context, boolean autoInitialize) {
|
|
51
|
+
this(context, autoInitialize, false);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Set up the sync adapter. This form of the
|
|
57
|
+
* constructor maintains compatibility with Android 3.0
|
|
58
|
+
* and later platform versions
|
|
59
|
+
*/
|
|
60
|
+
public SyncAdapter(
|
|
61
|
+
Context context,
|
|
62
|
+
boolean autoInitialize,
|
|
63
|
+
boolean allowParallelSyncs) {
|
|
64
|
+
|
|
65
|
+
super(context, autoInitialize);
|
|
66
|
+
logger = LoggerManager.getLogger(SyncAdapter.class);
|
|
67
|
+
|
|
68
|
+
/*
|
|
69
|
+
* If your app uses a content resolver, get an instance of it
|
|
70
|
+
* from the incoming Context
|
|
71
|
+
*/
|
|
72
|
+
contentResolver = context.getContentResolver();
|
|
73
|
+
configDAO = DAOFactory.createConfigurationDAO(context);
|
|
74
|
+
batchManager = new BatchManager(this.getContext());
|
|
75
|
+
notificationManager = (NotificationManager) getContext().getSystemService(Context.NOTIFICATION_SERVICE);
|
|
76
|
+
|
|
77
|
+
NotificationHelper.registerSyncChannel(context);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Specify the code you want to run in the sync adapter. The entire
|
|
82
|
+
* sync adapter runs in a background thread, so you don't have to set
|
|
83
|
+
* up your own background processing.
|
|
84
|
+
*/
|
|
85
|
+
@Override
|
|
86
|
+
public void onPerformSync(
|
|
87
|
+
Account account,
|
|
88
|
+
Bundle extras,
|
|
89
|
+
String authority,
|
|
90
|
+
ContentProviderClient provider,
|
|
91
|
+
SyncResult syncResult) {
|
|
92
|
+
|
|
93
|
+
Config config = null;
|
|
94
|
+
try {
|
|
95
|
+
config = configDAO.retrieveConfiguration();
|
|
96
|
+
} catch (JSONException e) {
|
|
97
|
+
logger.error("Error retrieving config: {}", e.getMessage());
|
|
98
|
+
syncResult.stats.numParseExceptions++;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (config == null || !config.hasValidSyncUrl() || !Boolean.TRUE.equals(config.getSyncEnabled())) {
|
|
103
|
+
if (config == null) {
|
|
104
|
+
logger.warn("Sync skipped: no config");
|
|
105
|
+
} else if (!Boolean.TRUE.equals(config.getSyncEnabled())) {
|
|
106
|
+
logger.info("Sync skipped: sync disabled in config");
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
//noinspection ConstantConditions
|
|
112
|
+
notificationsEnabled = !config.hasNotificationsEnabled() || config.getNotificationsEnabled();
|
|
113
|
+
currentSyncConfig = config;
|
|
114
|
+
|
|
115
|
+
Long batchStartMillis = System.currentTimeMillis();
|
|
116
|
+
boolean isForced = (extras != null) && extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
|
|
117
|
+
Integer configThreshold = config.getSyncThreshold();
|
|
118
|
+
int syncThreshold = isForced ? 0 : (configThreshold != null ? configThreshold : 100);
|
|
119
|
+
logger.debug("Sync request isForced: {}, batchId: {}, syncThreshold: {}, config: {}", isForced, batchStartMillis, syncThreshold, config.toString());
|
|
120
|
+
|
|
121
|
+
File file = null;
|
|
122
|
+
try {
|
|
123
|
+
file = batchManager.createBatch(batchStartMillis, syncThreshold, config.getTemplate());
|
|
124
|
+
} catch (IOException e) {
|
|
125
|
+
logger.error("Failed to create batch: {}", e.getMessage());
|
|
126
|
+
syncResult.stats.numIoExceptions++;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (file == null) {
|
|
131
|
+
logger.info("Nothing to sync");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
logger.info("Syncing startAt: {}", batchStartMillis);
|
|
136
|
+
String url = config.getSyncUrl();
|
|
137
|
+
HashMap<String, String> httpHeaders = new HashMap<String, String>();
|
|
138
|
+
if (config.getHttpHeaders() != null) {
|
|
139
|
+
httpHeaders.putAll(config.getHttpHeaders());
|
|
140
|
+
}
|
|
141
|
+
httpHeaders.put("x-batch-id", String.valueOf(batchStartMillis));
|
|
142
|
+
|
|
143
|
+
// For URL templating in sync mode we can only resolve static queryParams keys; per-location
|
|
144
|
+
// placeholders (like {lat}) cannot apply to a multi-location batch. If the user wants per-location
|
|
145
|
+
// URL substitution they should use httpMode="single" + url= ... (real-time) or syncMode="single".
|
|
146
|
+
String resolvedUrl = com.marianhello.bgloc.http.UrlTemplateResolver.resolve(url, null, config.getQueryParams());
|
|
147
|
+
String syncMethod = config.getSyncHttpMethod();
|
|
148
|
+
if (uploadLocations(file, resolvedUrl, httpHeaders, syncMethod)) {
|
|
149
|
+
logger.info("Batch sync successful");
|
|
150
|
+
batchManager.setBatchCompleted(batchStartMillis);
|
|
151
|
+
if (file.delete()) {
|
|
152
|
+
logger.info("Batch file has been deleted: {}", file.getAbsolutePath());
|
|
153
|
+
} else {
|
|
154
|
+
logger.warn("Batch file has not been deleted: {}", file.getAbsolutePath());
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
logger.warn("Batch sync failed due server error");
|
|
158
|
+
syncResult.stats.numIoExceptions++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private boolean uploadLocations(File file, String url, HashMap httpHeaders, String method) {
|
|
163
|
+
NotificationCompat.Builder builder = null;
|
|
164
|
+
|
|
165
|
+
if (notificationsEnabled) {
|
|
166
|
+
builder = new NotificationCompat.Builder(getContext(), NotificationHelper.SYNC_CHANNEL_ID);
|
|
167
|
+
builder.setOngoing(true);
|
|
168
|
+
builder.setContentTitle(currentSyncConfig.getNotificationSyncTitle());
|
|
169
|
+
builder.setContentText(currentSyncConfig.getNotificationSyncText());
|
|
170
|
+
builder.setSmallIcon(android.R.drawable.ic_dialog_info);
|
|
171
|
+
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// v3.5 Phase 4: emit syncStart event.
|
|
175
|
+
Bundle syncStart = new Bundle();
|
|
176
|
+
syncStart.putInt("action", LocationServiceImpl.MSG_ON_SYNC_START);
|
|
177
|
+
broadcastMessage(syncStart);
|
|
178
|
+
|
|
179
|
+
// Count locations being uploaded (best-effort, API-21+ safe).
|
|
180
|
+
int locationsAttempted = 0;
|
|
181
|
+
java.io.FileInputStream fis = null;
|
|
182
|
+
try {
|
|
183
|
+
fis = new java.io.FileInputStream(file);
|
|
184
|
+
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
|
185
|
+
byte[] buf = new byte[4096];
|
|
186
|
+
int n;
|
|
187
|
+
while ((n = fis.read(buf)) > 0) baos.write(buf, 0, n);
|
|
188
|
+
org.json.JSONArray arr = new org.json.JSONArray(new String(baos.toByteArray(), "UTF-8"));
|
|
189
|
+
locationsAttempted = arr.length();
|
|
190
|
+
} catch (Throwable ignored) { /* best-effort; emit 0 if we cannot read */
|
|
191
|
+
} finally {
|
|
192
|
+
if (fis != null) try { fis.close(); } catch (Exception ignored) {}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
try {
|
|
196
|
+
int responseCode = HttpPostService.postJSONFile(url, file, httpHeaders, this, method);
|
|
197
|
+
|
|
198
|
+
// All 2xx statuses are okay
|
|
199
|
+
boolean isStatusOkay = responseCode >= 200 && responseCode < 300;
|
|
200
|
+
|
|
201
|
+
if (responseCode == 285) {
|
|
202
|
+
// Okay, but we don't need to continue sending these
|
|
203
|
+
|
|
204
|
+
logger.debug("Location was sent to the server, and received an \"HTTP 285 Updates Not Required\"");
|
|
205
|
+
|
|
206
|
+
Bundle bundle = new Bundle();
|
|
207
|
+
bundle.putInt("action", LocationServiceImpl.MSG_ON_ABORT_REQUESTED);
|
|
208
|
+
broadcastMessage(bundle);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (responseCode == 401) {
|
|
212
|
+
Bundle bundle = new Bundle();
|
|
213
|
+
bundle.putInt("action", LocationServiceImpl.MSG_ON_HTTP_AUTHORIZATION);
|
|
214
|
+
broadcastMessage(bundle);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (builder != null) {
|
|
218
|
+
if (isStatusOkay) {
|
|
219
|
+
builder.setContentText(currentSyncConfig.getNotificationSyncCompletedText());
|
|
220
|
+
} else {
|
|
221
|
+
builder.setContentText(currentSyncConfig.getNotificationSyncFailedText() + " (HTTP " + responseCode + ")");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!isStatusOkay) {
|
|
226
|
+
logger.warn("Batch sync failed: server returned HTTP {} (check server logs or sync URL)", responseCode);
|
|
227
|
+
Bundle errBundle = new Bundle();
|
|
228
|
+
errBundle.putInt("action", LocationServiceImpl.MSG_ON_SYNC_ERROR);
|
|
229
|
+
errBundle.putInt("httpStatus", responseCode);
|
|
230
|
+
errBundle.putString("message", "HTTP " + responseCode);
|
|
231
|
+
broadcastMessage(errBundle);
|
|
232
|
+
} else {
|
|
233
|
+
Bundle okBundle = new Bundle();
|
|
234
|
+
okBundle.putInt("action", LocationServiceImpl.MSG_ON_SYNC_SUCCESS);
|
|
235
|
+
okBundle.putInt("sent", locationsAttempted);
|
|
236
|
+
broadcastMessage(okBundle);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return isStatusOkay;
|
|
240
|
+
} catch (IOException e) {
|
|
241
|
+
String errMsg = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
|
|
242
|
+
logger.warn("Error uploading locations (network/IO): {}", errMsg);
|
|
243
|
+
|
|
244
|
+
if (builder != null) {
|
|
245
|
+
builder.setContentText(currentSyncConfig.getNotificationSyncFailedText() + ": " + errMsg);
|
|
246
|
+
}
|
|
247
|
+
Bundle errBundle = new Bundle();
|
|
248
|
+
errBundle.putInt("action", LocationServiceImpl.MSG_ON_SYNC_ERROR);
|
|
249
|
+
errBundle.putInt("httpStatus", 0);
|
|
250
|
+
errBundle.putString("message", errMsg);
|
|
251
|
+
broadcastMessage(errBundle);
|
|
252
|
+
} finally {
|
|
253
|
+
logger.info("Syncing endAt: {}", System.currentTimeMillis());
|
|
254
|
+
|
|
255
|
+
if (builder != null) {
|
|
256
|
+
builder.setOngoing(false);
|
|
257
|
+
builder.setProgress(0, 0, false);
|
|
258
|
+
builder.setAutoCancel(true);
|
|
259
|
+
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
|
260
|
+
|
|
261
|
+
Handler h = new Handler(Looper.getMainLooper());
|
|
262
|
+
long delayInMilliseconds = 5000;
|
|
263
|
+
h.postDelayed(new Runnable() {
|
|
264
|
+
public void run() {
|
|
265
|
+
logger.info("Notification cancelledAt: {}", System.currentTimeMillis());
|
|
266
|
+
notificationManager.cancel(NOTIFICATION_ID);
|
|
267
|
+
}
|
|
268
|
+
}, delayInMilliseconds);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public void onProgress(int progress) {
|
|
276
|
+
logger.debug("Syncing progress: {} updatedAt: {}", progress, System.currentTimeMillis());
|
|
277
|
+
|
|
278
|
+
Config c = currentSyncConfig;
|
|
279
|
+
if (notificationsEnabled && c != null) {
|
|
280
|
+
NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext(), NotificationHelper.SYNC_CHANNEL_ID);
|
|
281
|
+
builder.setOngoing(true);
|
|
282
|
+
builder.setContentTitle(c.getNotificationSyncTitle());
|
|
283
|
+
builder.setContentText(c.getNotificationSyncText());
|
|
284
|
+
builder.setSmallIcon(android.R.drawable.ic_dialog_info);
|
|
285
|
+
builder.setProgress(100, progress, false);
|
|
286
|
+
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// v3.5 Phase 4: forward progress percentage to JS via syncProgress event.
|
|
290
|
+
Bundle progBundle = new Bundle();
|
|
291
|
+
progBundle.putInt("action", LocationServiceImpl.MSG_ON_SYNC_PROGRESS);
|
|
292
|
+
progBundle.putInt("progress", progress);
|
|
293
|
+
broadcastMessage(progBundle);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
private void broadcastMessage(Bundle bundle) {
|
|
297
|
+
Intent intent = new Intent(LocationServiceImpl.ACTION_BROADCAST);
|
|
298
|
+
intent.putExtras(bundle);
|
|
299
|
+
LocalBroadcastManager.getInstance(getContext().getApplicationContext()).sendBroadcast(intent);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package com.marianhello.bgloc.sync;
|
|
2
|
+
|
|
3
|
+
import android.accounts.Account;
|
|
4
|
+
import android.app.Service;
|
|
5
|
+
import android.content.ContentResolver;
|
|
6
|
+
import android.content.Intent;
|
|
7
|
+
import android.os.Bundle;
|
|
8
|
+
import android.os.IBinder;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Define a Service that returns an IBinder for the
|
|
12
|
+
* sync adapter class, allowing the sync adapter framework to call
|
|
13
|
+
* onPerformSync().
|
|
14
|
+
*/
|
|
15
|
+
public class SyncService extends Service {
|
|
16
|
+
// Storage for an instance of the sync adapter
|
|
17
|
+
private static SyncAdapter sSyncAdapter = null;
|
|
18
|
+
// Object to use as a thread-safe lock
|
|
19
|
+
private static final Object sSyncAdapterLock = new Object();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Instantiate the sync adapter object.
|
|
23
|
+
*/
|
|
24
|
+
@Override
|
|
25
|
+
public void onCreate() {
|
|
26
|
+
/*
|
|
27
|
+
* Create the sync adapter as a singleton.
|
|
28
|
+
* Set the sync adapter as syncable
|
|
29
|
+
* Disallow parallel syncs
|
|
30
|
+
*/
|
|
31
|
+
synchronized (sSyncAdapterLock) {
|
|
32
|
+
if (sSyncAdapter == null) {
|
|
33
|
+
sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Return an object that allows the system to invoke
|
|
40
|
+
* the sync adapter.
|
|
41
|
+
*
|
|
42
|
+
*/
|
|
43
|
+
@Override
|
|
44
|
+
public IBinder onBind(Intent intent) {
|
|
45
|
+
/*
|
|
46
|
+
* Get the object that allows external processes
|
|
47
|
+
* to call onPerformSync(). The object is created
|
|
48
|
+
* in the base class code when the SyncAdapter
|
|
49
|
+
* constructors call super()
|
|
50
|
+
*/
|
|
51
|
+
return sSyncAdapter.getSyncAdapterBinder();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static void sync(Account account, String authority, boolean manual) {
|
|
55
|
+
// Pass the settings flags by inserting them in a bundle
|
|
56
|
+
Bundle settingsBundle = new Bundle();
|
|
57
|
+
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, manual);
|
|
58
|
+
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, manual);
|
|
59
|
+
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false);
|
|
60
|
+
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* Request the sync for the default account, authority, and
|
|
64
|
+
* manual sync settings
|
|
65
|
+
*/
|
|
66
|
+
ContentResolver.requestSync(account, authority, settingsBundle);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
package com.marianhello.logging;
|
|
2
|
+
|
|
3
|
+
import android.database.Cursor;
|
|
4
|
+
import android.database.sqlite.SQLiteDatabase;
|
|
5
|
+
import android.database.sqlite.SQLiteException;
|
|
6
|
+
|
|
7
|
+
import ru.andremoniy.sqlbuilder.SqlExpression;
|
|
8
|
+
import ru.andremoniy.sqlbuilder.SqlSelectStatement;
|
|
9
|
+
|
|
10
|
+
import org.slf4j.event.Level;
|
|
11
|
+
|
|
12
|
+
import java.io.File;
|
|
13
|
+
import java.sql.SQLException;
|
|
14
|
+
import java.util.ArrayList;
|
|
15
|
+
import java.util.Collection;
|
|
16
|
+
|
|
17
|
+
import ch.qos.logback.classic.LoggerContext;
|
|
18
|
+
import ch.qos.logback.classic.db.names.ColumnName;
|
|
19
|
+
import ch.qos.logback.classic.db.names.DBNameResolver;
|
|
20
|
+
import ch.qos.logback.classic.db.names.DefaultDBNameResolver;
|
|
21
|
+
import ch.qos.logback.classic.db.names.TableName;
|
|
22
|
+
import ch.qos.logback.core.CoreConstants;
|
|
23
|
+
// NOTE: logback-android 2.x / 3.x dropped `ch.qos.logback.core.android.CommonPathUtil`.
|
|
24
|
+
// The dropped util only computed `/data/data/<pkg>/databases`, so we inline that
|
|
25
|
+
// path below. Adjusted from the upstream `mauron85/cordova-plugin-background-geolocation`
|
|
26
|
+
// source for Capacitor 8+ compatibility. Apache-2.0.
|
|
27
|
+
|
|
28
|
+
public class DBLogReader {
|
|
29
|
+
|
|
30
|
+
public static final String DB_FILENAME = "logback.db";
|
|
31
|
+
|
|
32
|
+
private DefaultDBNameResolver mDbNameResolver;
|
|
33
|
+
private SQLiteDatabase mDatabase;
|
|
34
|
+
|
|
35
|
+
public static class QueryBuilder {
|
|
36
|
+
DBNameResolver mDbNameResolver;
|
|
37
|
+
|
|
38
|
+
public QueryBuilder() {
|
|
39
|
+
mDbNameResolver = new DefaultDBNameResolver();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public QueryBuilder(DBNameResolver dbNameResolver) {
|
|
43
|
+
mDbNameResolver = dbNameResolver;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Generate array of levels that are same or above provided level
|
|
48
|
+
*
|
|
49
|
+
* @param level
|
|
50
|
+
* @return array of levels that are same or above level
|
|
51
|
+
*/
|
|
52
|
+
private Object[] aboveLevel(Level level) {
|
|
53
|
+
ArrayList<String> levels = new ArrayList();
|
|
54
|
+
for (Level l : Level.values()) {
|
|
55
|
+
if (level.compareTo(l) >= 0) {
|
|
56
|
+
levels.add(l.toString());
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return levels.toArray();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public String buildStackTraceQuery(int eventId) {
|
|
63
|
+
SqlSelectStatement builder = new SqlSelectStatement();
|
|
64
|
+
builder.column(mDbNameResolver.getColumnName(ColumnName.TRACE_LINE));
|
|
65
|
+
builder.from(mDbNameResolver.getTableName(TableName.LOGGING_EVENT_EXCEPTION));
|
|
66
|
+
builder.where(mDbNameResolver.getColumnName(ColumnName.I), SqlExpression.SqlOperatorEqualTo, Integer.valueOf(eventId));
|
|
67
|
+
builder.orderBy(mDbNameResolver.getColumnName(ColumnName.I));
|
|
68
|
+
|
|
69
|
+
return builder.statement();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public String buildQuery(int limit, int fromLogEntryId, Level minLevel) {
|
|
73
|
+
SqlSelectStatement builder = new SqlSelectStatement();
|
|
74
|
+
builder.columns(new String[]{
|
|
75
|
+
mDbNameResolver.getColumnName(ColumnName.EVENT_ID),
|
|
76
|
+
mDbNameResolver.getColumnName(ColumnName.TIMESTMP),
|
|
77
|
+
mDbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE),
|
|
78
|
+
mDbNameResolver.getColumnName(ColumnName.LOGGER_NAME),
|
|
79
|
+
mDbNameResolver.getColumnName(ColumnName.LEVEL_STRING),
|
|
80
|
+
});
|
|
81
|
+
builder.from(mDbNameResolver.getTableName(TableName.LOGGING_EVENT));
|
|
82
|
+
builder.where(mDbNameResolver.getColumnName(ColumnName.LEVEL_STRING), SqlExpression.SqlOperatorIn, aboveLevel(minLevel));
|
|
83
|
+
if (fromLogEntryId > 0) {
|
|
84
|
+
if (limit >= 0) {
|
|
85
|
+
builder.where(mDbNameResolver.getColumnName(ColumnName.EVENT_ID), SqlExpression.SqlOperatorLessThan, fromLogEntryId);
|
|
86
|
+
} else {
|
|
87
|
+
builder.where(mDbNameResolver.getColumnName(ColumnName.EVENT_ID), SqlExpression.SqlOperatorGreaterThan, fromLogEntryId);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (limit < 0) {
|
|
91
|
+
builder.orderBy(mDbNameResolver.getColumnName(ColumnName.TIMESTMP));
|
|
92
|
+
builder.orderBy(mDbNameResolver.getColumnName(ColumnName.EVENT_ID));
|
|
93
|
+
} else {
|
|
94
|
+
builder.orderBy(mDbNameResolver.getColumnName(ColumnName.TIMESTMP), true);
|
|
95
|
+
builder.orderBy(mDbNameResolver.getColumnName(ColumnName.EVENT_ID), true);
|
|
96
|
+
}
|
|
97
|
+
builder.limit(limit);
|
|
98
|
+
|
|
99
|
+
return builder.statement();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public Collection<LogEntry> getEntries(int limit, int fromLogEntryId, Level minLevel) {
|
|
104
|
+
try {
|
|
105
|
+
return getDbEntries(limit, fromLogEntryId, minLevel);
|
|
106
|
+
} catch (SQLException e) {
|
|
107
|
+
e.printStackTrace();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private SQLiteDatabase openDatabase() throws SQLException {
|
|
114
|
+
if (mDatabase != null && mDatabase.isOpen()) {
|
|
115
|
+
return mDatabase;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
String packageName = null;
|
|
119
|
+
LoggerContext context = (LoggerContext) org.slf4j.LoggerFactory.getILoggerFactory();
|
|
120
|
+
|
|
121
|
+
if (context != null) {
|
|
122
|
+
packageName = context.getProperty(CoreConstants.PACKAGE_NAME_KEY);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (packageName == null || packageName.length() == 0) {
|
|
126
|
+
throw new SQLException("Cannot open database without package name");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// Android stores app-private databases at `/data/data/<package>/databases`.
|
|
131
|
+
File dbDir = new File("/data/data/" + packageName + "/databases");
|
|
132
|
+
File dbfile = new File(dbDir, DB_FILENAME);
|
|
133
|
+
mDatabase = SQLiteDatabase.openDatabase(dbfile.getPath(), null, SQLiteDatabase.OPEN_READONLY);
|
|
134
|
+
} catch (SQLiteException e) {
|
|
135
|
+
throw new SQLException("Cannot open database", e);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return mDatabase;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private DefaultDBNameResolver getDbNameResolver() {
|
|
142
|
+
if (mDbNameResolver != null) {
|
|
143
|
+
return mDbNameResolver;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
mDbNameResolver = new DefaultDBNameResolver();
|
|
147
|
+
return mDbNameResolver;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private Collection<String> getStackTrace(int logEntryId) throws SQLException {
|
|
151
|
+
Collection<String> stackTrace = new ArrayList();
|
|
152
|
+
SQLiteDatabase db = openDatabase();
|
|
153
|
+
Cursor cursor = null;
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
DefaultDBNameResolver dbNameResolver = getDbNameResolver();
|
|
157
|
+
QueryBuilder qb = new QueryBuilder(dbNameResolver);
|
|
158
|
+
cursor = mDatabase.rawQuery(qb.buildStackTraceQuery(logEntryId), new String[] {});
|
|
159
|
+
while (cursor.moveToNext()) {
|
|
160
|
+
stackTrace.add(cursor.getString(cursor.getColumnIndex(dbNameResolver.getColumnName(ColumnName.TRACE_LINE))));
|
|
161
|
+
}
|
|
162
|
+
} catch (SQLiteException e) {
|
|
163
|
+
throw new SQLException("Cannot retrieve log entries", e);
|
|
164
|
+
} finally {
|
|
165
|
+
if (cursor != null) {
|
|
166
|
+
cursor.close();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return stackTrace;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private Collection<LogEntry> getDbEntries(int limit, int fromLogEntryId, Level minLevel) throws SQLException {
|
|
174
|
+
Collection<LogEntry> entries = new ArrayList<LogEntry>();
|
|
175
|
+
SQLiteDatabase db = openDatabase();
|
|
176
|
+
Cursor cursor = null;
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
DefaultDBNameResolver dbNameResolver = getDbNameResolver();
|
|
180
|
+
QueryBuilder qb = new QueryBuilder(dbNameResolver);
|
|
181
|
+
cursor = db.rawQuery(qb.buildQuery(limit, fromLogEntryId, minLevel), new String[] {});
|
|
182
|
+
while (cursor.moveToNext()) {
|
|
183
|
+
LogEntry entry = new LogEntry();
|
|
184
|
+
entry.setContext(0);
|
|
185
|
+
entry.setId(cursor.getInt(cursor.getColumnIndex(mDbNameResolver.getColumnName(ColumnName.EVENT_ID))));
|
|
186
|
+
entry.setLevel(cursor.getString(cursor.getColumnIndex(dbNameResolver.getColumnName(ColumnName.LEVEL_STRING))));
|
|
187
|
+
entry.setMessage(cursor.getString(cursor.getColumnIndex(dbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE))));
|
|
188
|
+
entry.setTimestamp(cursor.getLong(cursor.getColumnIndex(dbNameResolver.getColumnName(ColumnName.TIMESTMP))));
|
|
189
|
+
entry.setLoggerName(cursor.getString(cursor.getColumnIndex(dbNameResolver.getColumnName(ColumnName.LOGGER_NAME))));
|
|
190
|
+
if ("ERROR".equals(entry.getLevel())) {
|
|
191
|
+
entry.setStackTrace(getStackTrace(entry.getId()));
|
|
192
|
+
}
|
|
193
|
+
entries.add(entry);
|
|
194
|
+
}
|
|
195
|
+
} catch (SQLiteException e) {
|
|
196
|
+
throw new SQLException("Cannot retrieve log entries", e);
|
|
197
|
+
} finally {
|
|
198
|
+
if (cursor != null) {
|
|
199
|
+
cursor.close();
|
|
200
|
+
}
|
|
201
|
+
if (db != null) {
|
|
202
|
+
db.close();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return entries;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
package com.marianhello.logging;
|
|
2
|
+
|
|
3
|
+
import org.json.JSONException;
|
|
4
|
+
import org.json.JSONObject;
|
|
5
|
+
|
|
6
|
+
import java.util.Collection;
|
|
7
|
+
|
|
8
|
+
public class LogEntry {
|
|
9
|
+
private Integer id;
|
|
10
|
+
private Integer context;
|
|
11
|
+
private String level;
|
|
12
|
+
private String message;
|
|
13
|
+
private Long timestamp;
|
|
14
|
+
private String loggerName;
|
|
15
|
+
private Collection<String> stackTrace;
|
|
16
|
+
|
|
17
|
+
public Integer getId() {
|
|
18
|
+
return id;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public void setId(Integer id) {
|
|
22
|
+
this.id = id;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public Integer getContext() {
|
|
26
|
+
return context;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public void setContext(Integer context) {
|
|
30
|
+
this.context = context;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public String getLevel() {
|
|
34
|
+
return level;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public void setLevel(String level) {
|
|
38
|
+
this.level = level;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public String getMessage() {
|
|
42
|
+
return message;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public void setMessage(String message) {
|
|
46
|
+
this.message = message;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public Long getTimestamp() {
|
|
50
|
+
return timestamp;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public void setTimestamp(Long timestamp) {
|
|
54
|
+
this.timestamp = timestamp;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public String getLoggerName() {
|
|
58
|
+
return loggerName;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public void setLoggerName(String loggerName) {
|
|
62
|
+
this.loggerName = loggerName;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public boolean hasStackTrace() {
|
|
66
|
+
return stackTrace != null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public String getStackTrace() {
|
|
70
|
+
if (this.stackTrace == null) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
StringBuilder stackTraceBuilder = new StringBuilder();
|
|
75
|
+
for (String traceLine : this.stackTrace) {
|
|
76
|
+
stackTraceBuilder.append(traceLine).append("\n");
|
|
77
|
+
}
|
|
78
|
+
return stackTraceBuilder.toString();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public void setStackTrace(Collection<String> stackTrace) {
|
|
82
|
+
this.stackTrace = stackTrace;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public JSONObject toJSONObject() throws JSONException {
|
|
86
|
+
JSONObject json = new JSONObject();
|
|
87
|
+
json.put("id", this.id);
|
|
88
|
+
json.put("context", this.context);
|
|
89
|
+
json.put("level", this.level);
|
|
90
|
+
json.put("message", this.message);
|
|
91
|
+
json.put("timestamp", this.timestamp);
|
|
92
|
+
json.put("logger", this.loggerName);
|
|
93
|
+
if (hasStackTrace()) {
|
|
94
|
+
json.put("stackTrace", this.getStackTrace());
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return json;
|
|
98
|
+
}
|
|
99
|
+
}
|