transistorsoft / cordova-background-geolocation-lt

The most sophisticated background location-tracking & geofencing module with battery-conscious motion-detection intelligence for iOS and Android.
http://www.transistorsoft.com/shop/products/cordova-background-geolocation
Other
655 stars 277 forks source link

App crashes when permissions denied #1331

Closed UglyBlueCat closed 2 years ago

UglyBlueCat commented 2 years ago

Your Environment

Expected Behavior

When the user denies all tracking permissions the app should continue without tracking

Actual Behavior

The app closes if all tracking permissions are denied

Steps to Reproduce

  1. install app
  2. start app
  3. deny all tricking permissions when requested
  4. app closes

All relevant code should be below.

Tracking is initiated by calling setupBackgroundGeolocation() after login.

locTimeInterval defaults to 15

var bgConfig = null;

function setupBackgroundGeolocation() {
    const TAG = "setupBackgroundGeolocation | ";
    console.log(TAG);
    loadTrackingOptions();

  BackgroundGeolocation.onLocation(function(location) {
        const TAG = "setupBackgroundGeolocation.onLocation() | ";
        console.log(TAG+"location: "+JSON.stringify(location));
        checkLocationPertinence(location);
  });

  BackgroundGeolocation.onMotionChange(function(event) {
  });

  BackgroundGeolocation.onHttp(function(response) {
  });

  BackgroundGeolocation.onProviderChange(function(event) {
  });

  // 2. Execute #ready method:
  BackgroundGeolocation.ready(bgConfig,
        function(state) {
            const TAG = "setupBackgroundGeolocation.ready() | success | ";
            console.log(TAG);
        if (!state.enabled) startBackgroundGeolocation();
      },
        function(error) {
            const TAG = "setupBackgroundGeolocation.ready() | ";
            console.log(TAG+"failure | error: "+error);
            sendAnalytics(TAG,"failure | error: "+error);
      }
    );
}

function startBackgroundGeolocation() {
    const TAG = "startBackgroundGeolocation | ";
    console.log(TAG);
    BackgroundGeolocation.start(
    function(state) {
        const FTAG = TAG+"start | success | ";
        console.log(FTAG);
    }, 
    function(error) {
        const FTAG = TAG+"start | failure | ";
        console.log(FTAG+"error: "+error);
        sendAnalytics(FTAG,"failure | error: "+error);
    });
}

function setBackgroundGeolocationConfig() {
    const TAG = "setBackgroundGeolocationConfig | ";
    loadTrackingOptions();

    BackgroundGeolocation.setConfig(bgConfig,
        function(state) {
        if (!state.enabled) startBackgroundGeolocation();
        },
        function(error) {
            console.log(TAG+"failure | error: "+error);
            sendAnalytics(TAG,"failure | error: "+error);
        }
    );
}

function loadTrackingOptions() {
    const TAG = "loadTrackingOptions | ";
    console.log(TAG);
    bgConfig = {
        isMoving: true,
        reset: true,
        debug: false,
        logLevel: BackgroundGeolocation.LOG_LEVEL_WARN,
        desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
        distanceFilter: 0,
        disableElasticity: true,
        fastestLocationUpdateInterval: 15000,
        locationUpdateInterval: locTimeInterval*1000,
        disableStopDetection: true,
        autoSync: true,
        stopOnTerminate: false,
        startOnBoot: true,
        maxRecordsToPersist: 0,
        backgroundPermissionRationale: {
            message: 'Location information is used for lone worker protection and scheduling. Sending locations can be turned on or off by clicking the Okappy icon from within the app'
        }
    };

    locTimeInterval = getLocalStorageItem('locTimeInterval', locTimeInterval);
    byDistance = getLocalStorageItem('byDistance', byDistance);
    locDistanceInterval = getLocalStorageItem('locDistanceInterval', locDistanceInterval);

    bgConfig.locationUpdateInterval = locTimeInterval*1000;
}

Context

We have to be able to allow our users the choice of denying tracking permissions

Debug logs

Logs ``` D/SystemWebChromeClient: file:///android_asset/www/js/index.js: Line 98 : Received Event: deviceready I/chromium: [INFO:CONSOLE(98)] "Received Event: deviceready", source: file:///android_asset/www/js/index.js (98) D/FCMPlugin: Token: e_xW4pl8QIm7h-CUsWgUXx:APA91bFPXrgX0uRtL_cy-ZKw-nYXw0oDNRkvCQmTlUHdGxQJTzMoG4mmqTX_jI55gdQdlsKgKda8iksMIS3aD3hqEdd9-ESaJyLRFGMlEfRFDko0MELJ6HkIGJOcim0km3M9n8TzYgGu D/SystemWebChromeClient: file:///android_asset/www/js/autoalert_generalMobile.js: Line 1007 : onNotification callback successfully registered: OK I/chromium: [INFO:CONSOLE(1007)] "onNotification callback successfully registered: OK", source: file:///android_asset/www/js/autoalert_generalMobile.js (1007) D/SystemWebChromeClient: file:///android_asset/www/js/autoalert_sendLocation.js: Line 28 : setupBackgroundGeolocation | I/chromium: [INFO:CONSOLE(28)] "setupBackgroundGeolocation | ", source: file:///android_asset/www/js/autoalert_sendLocation.js (28) D/SystemWebChromeClient: file:///android_asset/www/js/autoalert_sendLocation.js: Line 93 : loadTrackingOptions | I/chromium: [INFO:CONSOLE(93)] "loadTrackingOptions | ", source: file:///android_asset/www/js/autoalert_sendLocation.js (93) W/m.okappy.okapp: Accessing hidden method Landroid/app/AppGlobals;->getInitialApplication()Landroid/app/Application; (unsupported, reflection, allowed) D/EventBus: No subscribers registered for event class com.transistorsoft.locationmanager.event.ConfigChangeEvent D/EventBus: No subscribers registered for event class org.greenrobot.eventbus.NoSubscriberEvent D/TSLocationManager: [c.t.l.logger.LoggerFacade$a a] ℹ️ Persist config, dirty: [] D/TSLocationManager: [c.t.l.logger.LoggerFacade$a a] ℹ️ Persist config, dirty: [headlessJobService] I/TSLocationManager: [c.t.l.logger.LoggerFacade$a a] ✅ Google Play Services: connected (version code:12451000) I/TSLocationManager: [c.t.l.a.BackgroundGeolocation d] 🎾 Start monitoring location-provider changes D/TSLocationManager: $ addLocationListener() D/TSLocationManager: $ addMotionChangeListener() D/TSLocationManager: $ addHttpListener() D/TSLocationManager: $ addProviderChangeListener() D/TSLocationManager: $ ready() D/TSLocationManager: [c.t.l.data.sqlite.a onCreate] CREATE TABLE IF NOT EXISTS locations (id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT NOT NULL DEFAULT '', timestamp TEXT, json TEXT, data BLOB, encrypted BOOLEAN NOT NULL DEFAULT 0, locked BOOLEAN NOT NULL DEFAULT 0); D/TSLocationManager: [c.t.l.adapter.TSConfig d] ℹ️ Persist config, dirty: [backgroundPermissionRationale, backgroundPermissionRationale.message, debug, desiredAccuracy, disableElasticity, disableStopDetection, distanceFilter, fastestLocationUpdateInterval, isMoving, locationUpdateInterval, logLevel, maxRecordsToPersist, startOnBoot, stopOnTerminate] D/TSLocationManager: [c.t.l.data.sqlite.a onCreate] CREATE TABLE IF NOT EXISTS geofences (id INTEGER PRIMARY KEY AUTOINCREMENT, identifier TEXT NOT NULL UNIQUE, latitude DOUBLE NOT NULL, sin_latitude DOUBLE NOT NULL, cos_latitude DOUBLE NOT NULL, longitude DOUBLE NOT NULL, sin_longitude DOUBLE NOT NULL, cos_longitude DOUBLE NOT NULL, radius DOUBLE NOT NULL, notifyOnEntry BOOLEAN NOT NULL DEFAULT 0, notifyOnExit BOOLEAN NOT NULL DEFAULT 0, notifyOnDwell BOOLEAN NOT NULL DEFAULT 0, loiteringDelay INTEGER NOT NULL DEFAULT 0, extras TEXT); D/TSLocationManager: [c.t.l.data.sqlite.b prune] ℹ️ PRUNE -1 days W/PluginManager: THREAD WARNING: exec() call to BackgroundGeolocation.ready blocked the main thread for 19ms. Plugin should use CordovaInterface.getThreadPool(). D/TSLocationManager: $ start() D/SystemWebChromeClient: file:///android_asset/www/js/autoalert_sendLocation.js: Line 50 : setupBackgroundGeolocation.ready() | success | I/chromium: [INFO:CONSOLE(50)] "setupBackgroundGeolocation.ready() | success | ", source: file:///android_asset/www/js/autoalert_sendLocation.js (50) I/TSLocationManager: [c.t.locationmanager.util.c g] 🔵 LocationAuthorization: Requesting Background permission D/SystemWebChromeClient: file:///android_asset/www/js/autoalert_sendLocation.js: Line 63 : startBackgroundGeolocation | I/chromium: [INFO:CONSOLE(63)] "startBackgroundGeolocation | ", source: file:///android_asset/www/js/autoalert_sendLocation.js (63) V/FA: onActivityCreated W/m.okappy.okapp: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (unsupported, reflection, allowed) W/m.okappy.okapp: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (unsupported, reflection, allowed) V/FA: Activity resumed, time: 2318623730 V/FA: Screen exposed for less than 1000 ms. Event not sent. time: 77 V/FA: Activity paused, time: 2318623808 W/Choreographer: Frame time is 0.070683 ms in the future! Check that graphics HAL is generating vsync timestamps using the correct timebase. D/CordovaWebViewImpl: onPageFinished(file:///android_asset/www/index.html) D/FA: Application going to the background D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: com.okappy.okappy, PID: 28732 java.lang.AbstractMethodError: abstract method "void com.intentfilter.androidpermissions.PermissionManager$PermissionRequestListener.onPermissionDenied(com.intentfilter.androidpermissions.models.DeniedPermissions)" at com.intentfilter.androidpermissions.PermissionHandler.informPermissionsDenied(PermissionHandler.java:102) at com.intentfilter.androidpermissions.PermissionHandler.onPermissionsResult(PermissionHandler.java:57) at com.intentfilter.androidpermissions.PermissionManager.onReceive(PermissionManager.java:60) at androidx.localbroadcastmanager.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:313) at androidx.localbroadcastmanager.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:121) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7839) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) D/CompatibilityChangeReporter: Compat change id reported: 160794467; UID 10776; state: DISABLED E/TSLocationManager: [c.t.l.a.BackgroundGeolocation$x0 uncaughtException] ‼️ Uncaught Exception: abstract method "void com.intentfilter.androidpermissions.PermissionManager$PermissionRequestListener.onPermissionDenied(com.intentfilter.androidpermissions.models.DeniedPermissions)" {"activityRecognitionInterval":10000,"allowIdenticalLocations":false,"authorization":{},"autoSync":true,"autoSyncThreshold":0,"backgroundPermissionRationale":{"title":"Allow {applicationName} to access this device's location even when closed or not in use?","message":"Location information is used for lone worker protection and scheduling. Sending locations can be turned on or off by clicking the Okappy icon from within the app","positiveAction":"Change to \"{backgroundPermissionOptionLabel}\"","negativeAction":""},"batchSync":false,"configUrl":"","debug":true,"deferTime":0,"desiredAccuracy":-1,"desiredOdometerAccuracy":100,"disableAutoSyncOnCellular":false,"disableElasticity":true,"disableLocationAuthorizationAlert":false,"disableMotionActivityUpdates":false,"disableStopDetection":true,"distanceFilter":0,"elasticityMultiplier":1,"enableHeadless":false,"enableTimestampMeta":false,"extras":{},"fastestLocationUpdateInterval":15000,"foregroundService":true,"geofenceInitialTriggerEntry":true,"geofenceModeHighAccuracy":false,"geofenceProximityRadius":1000,"geofenceTemplate":"","headers":{},"headlessJobService":"com.transistorsoft.cordova.bggeo.BackgroundGeolocationHeadlessTask","heartbeatInterval":-1,"httpRootProperty":"location","httpTimeout":60000,"isMoving":true,"locationAuthorizationRequest":"Always","locationTemplate":"","locationTimeout":60,"locationUpdateInterval":15000,"locationsOrderDirection":"ASC","logLevel":5,"logMaxDays":3,"maxBatchSize":-1,"maxDaysToPersist":1,"maxRecordsToPersist":0,"method":"POST","minimumActivityRecognitionConfidence":75,"motionTriggerDelay":0,"notification":{"layout":"","title":"","text":"Location Service activated","color":"","channelName":"TSLocationManager","smallIcon":"","largeIcon":"","priority":0,"sticky":false,"strings":{},"actions":[]},"params":{},"persist":true,"persistMode":2,"schedule":[],"scheduleUseAlarmManager":false,"speedJumpFilter":300,"startOnBoot":true,"stationaryRadius":25,"stopAfterElapsedMinutes":0,"stopOnStationary":false,"stopOnTerminate":false,"stopTimeout":5,"triggerActivities":"in_vehicle, on_bicycle, on_foot, running, walking","url":"","useSignificantChangesOnly":false,"enabled":false,"schedulerEnabled":false,"trackingMode":1,"odometer":0,"isFirstBoot":true,"didLaunchInBackground":false,"didDeviceReboot":false} java.lang.AbstractMethodError: abstract method "void com.intentfilter.androidpermissions.PermissionManager$PermissionRequestListener.onPermissionDenied(com.intentfilter.androidpermissions.models.DeniedPermissions)" at com.intentfilter.androidpermissions.PermissionHandler.informPermissionsDenied(PermissionHandler.java:102) at com.intentfilter.androidpermissions.PermissionHandler.onPermissionsResult(PermissionHandler.java:57) at com.intentfilter.androidpermissions.PermissionManager.onReceive(PermissionManager.java:60) at androidx.localbroadcastmanager.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:313) at androidx.localbroadcastmanager.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:121) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7839) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) I/Process: Sending signal. PID: 28732 SIG: 9 ```
UglyBlueCat commented 2 years ago

I did a little more digging after looking more closely at the log, since com.intentfilter.androidpermissions.PermissionManager isn't one of yours. I found https://github.com/nishkarsh/android-permissions. A couple of find/grep commands found: ./plugins/cordova-background-geolocation-lt/plugin.xml: <framework src="io.github.nishkarsh:android-permissions:0.1.8"/> ./node_modules/cordova-background-geolocation-lt/plugin.xml: <framework src="io.github.nishkarsh:android-permissions:0.1.8"/>

I tried changing 0.1.8 in both files to 2.0.54 which didn't help

christocracy commented 2 years ago

The plugin requires android-permissions@0.1.8. You cannot use 2.0.54.

I cannot reproduce this error with the sample app.

UglyBlueCat commented 2 years ago

Can you see any issues with my config or the way I'm calling your plugin?

UglyBlueCat commented 2 years ago

Is there anything you could suggest I look for that may be causing android-permissions to crash when permission is denied?

UglyBlueCat commented 2 years ago

I appreciate your time with this and I apologise if I seem insistent, but I'm under pressure to get this working since my boss bought a licence this morning.

UglyBlueCat commented 2 years ago

Hi Chris,

I have posted an issue with android-permissions regarding this.

Here is his response:

"This doesn't indicate a problem in the implementation of the original library but the way it's being used. There seems to be a mismatch in the dependency version that the npm plugin might be using and the implementation of the request listener that it has defined."

christocracy commented 2 years ago

Create for me a simple hello-world app in a fresh new GitHub repo. Share that repo here with me.

UglyBlueCat commented 2 years ago

Hi,

Here is the base cordova getting started app in the same environment as our main app that has the problem, i.e. cordova 9 with platform android 7.1.2:

https://github.com/UglyBlueCat/OkHelloWorld

I have also made sure it builds & runs in android studio as we do with our main app.

Thanks, Robin

christocracy commented 2 years ago

Why are you using Cordova 9? You know you won’t be able to release a Cordova 9 app to Play Store right? It will be rejected,

christocracy commented 2 years ago

Your OkHelloWorld is not a valid Cordova project.

christocracy commented 2 years ago

Why would a Cordova 9 app be rejected by Google Play Store? Because the minimum api level for Android apps is now >= 29.

A Cordova 9 app uses API level 27.

UglyBlueCat commented 2 years ago

Thank you for your help

I took all your comments into consideration, created a new cordova project for our live app and it now works as expected.

Thanks :)