transistorsoft / flutter_background_geolocation

Sophisticated, battery-conscious background-geolocation & geofencing with motion-detection
https://www.transistorsoft.com/shop/products/flutter-background-geolocation
Other
629 stars 231 forks source link

Location update not received when app is in swiped from recent or phone reboots #536

Closed erluxman closed 3 years ago

erluxman commented 3 years ago

Let's start with our requirement.

To put it simply, we recive onLocationUpdate from phone and group the data of those snapshots to detech user's tips and reward them for using sustainable transport modes like bike, walk, train etc.

As soon as we get onLocation update we push it to our firebase backend which has a cache enabled so that even when device is offline, it records and syncs later when internet is availiable.

How it is supposed to work?

App gets location updates from this plugin when app is in foreground, when minimized, when swipe closed from recent menu and when device is rebooted.

How it behaves?

App works fine when its in foreground and its minimized but, once the app is swiped off from recent, killed by the OS or device reboots, we can't recive location updates automatically. But when app is in debug mode, I can hear the sounds I think it's heartbeat but it isn't recorded in firestore.

Then I thought there might be issue with adding object to firestore so I tried to add the onLocation update events inshared preferences but even that doesn't provide any evidence that onLocation update was called.

In Android I can hear the sound most of the time, but in iOS it's kind of random, sometimes I hear the sound when I am driving sometimes I can't.

My setup

Flutter doctor


[✓] Flutter (Channel stable, 2.0.0, on macOS 11.0.1 20B50 darwin-x64, locale en-US)
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] VS Code (version 1.54.3)
[✓] Connected device (2 available)

Android Manifest


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.greenplayapp">

    <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

    <application
        android:label="Défi sans auto solo"
        tools:replace="android:label"
        android:usesCleartextTraffic="true"
        android:name=".Application"
        android:icon="@mipmap/launcher_icon">

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

        <meta-data android:name="com.transistorsoft.locationmanager.license" android:value="licence" />
        <meta-data android:name="com.google.android.geo.API_KEY" android:value="apikey"/>
        <service android:name="com.transistorsoft.locationmanager.service.TrackingService" android:foregroundServiceType="location" />
        <service android:name="com.transistorsoft.locationmanager.service.LocationRequestService" android:foregroundServiceType="location" />
    </application>
</manifest>

Android App Gradle

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

// flutter_background_geolocation
Project background_geolocation = project(':flutter_background_geolocation')
apply from: "${background_geolocation.projectDir}/background_geolocation.gradle"

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        applicationId "com.greenplayapp"
        minSdkVersion 16
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1038
        versionName "1.0.38"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        ndk {
            abiFilters 'armeabi-v7a','arm64-v8a','x86_64'
        }
    }
    signingConfigs {
        release {
            storeFile file('keystore.jks')
            storePassword "paass"
            keyAlias "alias"
            keyPassword "pass"
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            shrinkResources false
            useProguard true
            proguardFiles "${background_geolocation.projectDir}/proguard-rules.pro"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

flutter {
    source '../..'
}

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    implementation 'com.android.support:multidex:1.0.3'
}
apply plugin: 'io.fabric'
apply plugin: 'com.google.gms.google-services'

Android Project Gradle


buildscript {
    ext {
        kotlin_version     = '1.3.72'
        compileSdkVersion   = 30
        targetSdkVersion    = 30
        appCompatVersion    = "1.2.0"
        playServicesLocationVersion = "17.1.0"
        removeBackgroundGeolocationDebugSoundsInRelease = false
    }
    repositories {
        google()
        jcenter()
        maven {
            url 'https://maven.fabric.io/public'
        }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'io.fabric.tools:gradle:1.28.0'
        classpath 'com.google.gms:google-services:4.3.3'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "${project(':background_fetch').projectDir}/libs"
        }
        maven {
            url "${project(':flutter_background_geolocation').projectDir}/libs"
        }
        maven {
            url 'http://download.flutter.io'
        }
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

iOS Plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>BACKGROUND_GEOLOCATION_ENCRYPTION_PASSWORD</key>
    <string>transistorsoft</string>
    <key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>com.transistorsoft.fetch</string>
    </array>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleLocalizations</key>
    <array>
        <string>en</string>
        <string>fr</string>
    </array>
    <key>CFBundleName</key>
    <string>Défi sans auto solo</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(MARKETING_VERSION)</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>com.googleusercontent.apps.336786091897-aubrenep3tmcskfdjbglhnebnjg9g09p</string>
            </array>
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>$(CURRENT_PROJECT_VERSION)</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    <key>NSAppleMusicUsageDescription</key>
    <string>Greenplay would like to access your music</string>
    <key>NSCalendarsUsageDescription</key>
    <string>Greenplay would like to access your calender</string>
    <key>NSCameraUsageDescription</key>
    <string>Greenplay would like to access your camera to let you update you profile picture</string>
    <key>NSContactsUsageDescription</key>
    <string>Greenplay would like to access your device contacts</string>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Greenplay wants to know your location to know how much distance you have covered for challenge</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>Greenplay wants to know your location to know how much distance you have covered for challenge</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>Greenplay would like to access your microphone</string>
    <key>NSMotionUsageDescription</key>
    <string>Greenplay wants to detect your motion to calculate your session</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>Greenplay would like to access your gallery to let you update you profile picture</string>
    <key>NSSpeechRecognitionUsageDescription</key>
    <string>Greenplay would like to access your device speech recognition</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
        <string>fetch</string>
        <string>location</string>
        <string>processing</string>
    </array>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
</dict>
</plist>

iOS Podfile


# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end

Dart main.dart


Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  await Firebase.initializeApp();
  runApp(App());
  BackgroundGeolocation.registerHeadlessTask(headlessTask);
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: RootScreen(),
    );
  }
}

Future<void> headlessTask(HeadlessEvent headlessEvent) async {
  print('Headless Event ${headlessEvent.name}  $headlessEvent');
  switch (headlessEvent.name) {
    case Event.TERMINATE:
      print("TERMINATE ${headlessEvent.event}");
      break;
    case Event.HEARTBEAT:
      print("HEARTBEAT ${headlessEvent.event}");
      SessionUploader.onLocationUpdate(
          (headlessEvent.event as HeartbeatEvent).location);
      break;
    case Event.LOCATION:
      print("LOCATION ${headlessEvent.event}");
      SessionUploader.onLocationUpdate(headlessEvent.event as Location);
      break;
    case Event.MOTIONCHANGE:
      print("MOTIONCHANGE ${headlessEvent.event}");
      SessionUploader.onLocationUpdate(headlessEvent.event as Location);
      break;
    case Event.GEOFENCE:
      print("GEOFENCE ${headlessEvent.event}");
      break;
    case Event.GEOFENCESCHANGE:
      print("GEOFENCESCHANGE ${headlessEvent.event}");
      break;
    case Event.SCHEDULE:
      print("SCHEDULE ${headlessEvent.event}");
      break;
    case Event.ACTIVITYCHANGE:
      print("ACTIVITYCHANGE ${headlessEvent.event}");
      break;
    case Event.HTTP:
      print("HTTP ${headlessEvent.event}");

      break;
    case Event.POWERSAVECHANGE:
      print("POWERSAVECHANGE ${headlessEvent.event}");

      break;
    case Event.CONNECTIVITYCHANGE:
      print("CONNECTIVITYCHANGE ${headlessEvent.event}");
      break;
    case Event.ENABLEDCHANGE:
      print("ENABLEDCHANGE ${headlessEvent.event}");
      break;
    case Event.AUTHORIZATION:
      print("AUTHORIZATION  ${headlessEvent.event}");
      break;
  }
}

Dart location_tracker.dart


class LocationTracker {

  Future<void> initTracking() async {
    await stopTracking();
    BackgroundGeolocation.changePace(true);
    BackgroundGeolocation.onLocation(SessionUploader.onLocationUpdateFg);
    // Configure
    BackgroundGeolocation.onMotionChange(SessionUploader.onLocationUpdateFg);
    BackgroundGeolocation.onHeartbeat(
        (hb) => SessionUploader.onLocationUpdateFg(hb.location));
    BackgroundGeolocation.ready(Config(
      desiredAccuracy: Config.DESIRED_ACCURACY_HIGH,
      stopOnTerminate: false,
      startOnBoot: true,
      notificationTitle: _prefs.getString("App Name"),
      notificationText: 'Fetching location',
      debug: true,
      logLevel: Config.LOG_LEVEL_VERBOSE,
      enableHeadless: true,
      forceReloadOnBoot: true,
      forceReloadOnGeofence: true,
      forceReloadOnHeartbeat: true,
      forceReloadOnLocationChange: true,
      forceReloadOnMotionChange: true,
      forceReloadOnSchedule: true,
      isMoving: true,
      disableElasticity: true,
      foregroundService: true,
      distanceFilter: 2.0,
      stopTimeout: 5,
      backgroundPermissionRationale: PermissionRationale(
          title:
              "Allow  Greenplay to access this device's location even when the app is closed or not in use.",
          message:
              "This app collects location data to enable recording your trips to work and calculate distance-travelled.",
          positiveAction: 'Change to Always allow',
          negativeAction: 'Cancel'),
      maxRecordsToPersist: 1000,
      allowIdenticalLocations: false,
      minimumActivityRecognitionConfidence: 75,
      fastestLocationUpdateInterval: 10 * 1000,
      heartbeatInterval: 60,
    )).then((State state) {
      if (!state.enabled) {
        BackgroundGeolocation.start();
      }
    });
  }

  Future<void> stopTracking() async {
    return BackgroundGeolocation.stop();
  }
}

Dart location_uploader.dart


class SessionUploader {
  static void onLocationUpdateFg(
    Location location,
  ) {
    onLocationUpdate(location, isFromForeground: true);
  }

  static Future<void> onLocationUpdate(
    Location location, {
    bool isFromForeground = false,
  }) async {
    if (DateTime.now().difference(lastUsed).inSeconds < 2) return;
    lastUsed = DateTime.now();
    //TODO use default Motor transport type if the transport type is "motor"

    //I used this shared preference setting to set location updates to shared preferences 
    // With doubt that firebase might have some issue or but it doesn't record either
    final trackedData = GreenPrefs.instance()
        .getString("trackingData", defaultValue: {}.toString());

    final Map<String, dynamic> data =
        json.decode(trackedData) as Map<String, dynamic>;

    //This is our representation of location snapshot
    final rawSession = RawSession(
      longitude: location.coords.longitude,
      latitude: location.coords.latitude,
      altitude: location.coords.altitude,
      timestamp: DateTime.parse(location.timestamp).millisecondsSinceEpoch,
      activityType:location.activity.type
    );
    data["${DateTime.now().toIso8601String()} @ ${location.activity.type}"] = rawSession.toMap();
    await GreenPrefs.instance().putString("trackingData", json.encode(data));
    if (isFromForeground) {
      //Only show toast if data is triggered from FG
      GreenToast.showToast(
        "${location.activity.type} => ${location.activity.type} " +
            "Default :$defaultTransportMode" +
            rawSession.toString(),
      );
    }
    //It uploads data to firestore
    SessionDataSource.instance().addRawSession(rawSession);

  }
}

So When app is in foregorund or minimized the SessionUploader.onLocationUpdate() is called and the data is saved in database and preferences but when app is removed from recent or phone reboot, I only hear the debug sound but no evidence of location update.

Why is this happening? Am I making any mistake or the plugin is limited?

christocracy commented 3 years ago

See Wiki Debugging to learn how to fetch an analyze the logs from the plugin with emailLog.

erluxman commented 3 years ago

Do I upload those logs here or send them to your email?

Do I have to provide my actual timeline along with these longs in another doc as well or log will be enough? By my actual timelin, I mean my manual records of the modes that I took and the time of those events?

erluxman commented 3 years ago

My Realtimeline.

I had changed my time from Nepal time to Quebec time for this test.

3:35 Closed all apps (iphone app,android app and sample app)
3:48 Opened all three apps
3:54 Closed all apps agan.  ( then drove for some time)
Took rest until 5:42 AM and started driving on motorbike
5:49 Rebooted device and unlocked it right after
5:56 Unlocked both devices again (as I didn’t hear debug sounds)- started hearing debug sound again.
6:06 Stopped.

iPhone logs

  {
    activityRecognitionInterval = 10000;
    activityType = 1;
    authorization =    {
    };
    autoSync = 1;
    autoSyncThreshold = 0;
    batchSync = 0;
    debug = 0;
    desiredAccuracy = "-1";
    desiredOdometerAccuracy = 100;
    didLaunchInBackground = 0;
    didRequestUpgradeLocationAuthorization = 1;
    disableAutoSyncOnCellular = 0;
    disableElasticity = 1;
    disableLocationAuthorizationAlert = 0;
    disableMotionActivityUpdates = 0;
    disableStopDetection = 0;
    distanceFilter = 2;
    elasticityMultiplier = 1;
    enableTimestampMeta = 0;
    enabled = 0;
    extras =    {
    };
    geofenceInitialTriggerEntry = 1;
    geofenceProximityRadius = 2000;
    geofenceTemplate = "";
    headers =    {
    };
    heartbeatInterval = 60;
    httpRootProperty = location;
    httpTimeout = 60000;
    iOSHasWarnedLocationServicesOff = 1;
    isFirstBoot = 0;
    isMoving = 0;
    lastLocationAuthorizationStatus = 3;
    locationAuthorizationAlert =    {
        cancelButton = Cancel;
        instructions = "To use background location, you must enable '{locationAuthorizationRequest}' in the Location Services settings";
        settingsButton = Settings;
        titleWhenNotEnabled = "Background location is not enabled";
        titleWhenOff = "Location services are off";
    };
    locationAuthorizationRequest = Always;
    locationTemplate = "";
    locationTimeout = 60;
    locationsOrderDirection = ASC;
    logLevel = 5;
    logMaxDays = 3;
    maxBatchSize = "-1";
    maxDaysToPersist = 1;
    maxRecordsToPersist = 1000;
    method = POST;
    minimumActivityRecognitionConfidence = 75;
    odometer = "11307.98223071513";
    params =    {
    };
    pausesLocationUpdatesAutomatically = 1;
    persistMode = 2;
    preventSuspend = 0;
    schedule =    (
    );
    schedulerEnabled = 0;
    showsBackgroundLocationIndicator = 0;
    startOnBoot = 1;
    stationaryRadius = 25;
    stopAfterElapsedMinutes = "-1";
    stopDetectionDelay = 0;
    stopOnStationary = 0;
    stopOnTerminate = 0;
    stopTimeout = 5;
    trackingMode = 1;
    url = "";
    useSignificantChangesOnly = 0;
}

background-geolocation_iphone.log

Android logs

I was using The sample app from transistorsoft as well to track the same trips the logs can be found here

Logs from our app is as follows :


╔═════════════════════════════════════════════
║ TSLocationManager version: 3.1.22 (378)
╠═════════════════════════════════════════════
╟─ Xiaomi POCO X2 @ 11 (flutter)
{
  "activityRecognitionInterval": 10000,
  "allowIdenticalLocations": false,
  "authorization": {},
  "autoSync": true,
  "autoSyncThreshold": 0,
  "backgroundPermissionRationale": {
    "title": "Allow  Greenplay to access this device's location even when the app is closed or not in use.",
    "message": "This app collects location data to enable recording your trips to work and calculate distance-travelled.",
    "positiveAction": "Change to Always allow",
    "negativeAction": "Cancel"
  },
  "batchSync": false,
  "configUrl": "",
  "debug": false,
  "deferTime": 0,
  "desiredAccuracy": -1,
  "desiredOdometerAccuracy": 100,
  "disableAutoSyncOnCellular": false,
  "disableElasticity": true,
  "disableLocationAuthorizationAlert": false,
  "disableMotionActivityUpdates": false,
  "disableStopDetection": false,
  "distanceFilter": 2,
  "elasticityMultiplier": 1,
  "enableHeadless": true,
  "enableTimestampMeta": false,
  "extras": {},
  "fastestLocationUpdateInterval": 10000,
  "foregroundService": true,
  "geofenceInitialTriggerEntry": true,
  "geofenceModeHighAccuracy": false,
  "geofenceProximityRadius": 1000,
  "geofenceTemplate": "",
  "headers": {},
  "headlessJobService": "com.transistorsoft.flutter.backgroundgeolocation.HeadlessTask",
  "heartbeatInterval": 60,
  "httpRootProperty": "location",
  "httpTimeout": 60000,
  "isMoving": true,
  "locationAuthorizationRequest": "Always",
  "locationTemplate": "",
  "locationTimeout": 60,
  "locationUpdateInterval": 1000,
  "locationsOrderDirection": "ASC",
  "logLevel": 5,
  "logMaxDays": 3,
  "maxBatchSize": -1,
  "maxDaysToPersist": 1,
  "maxRecordsToPersist": 1000,
  "method": "POST",
  "minimumActivityRecognitionConfidence": 75,
  "motionTriggerDelay": 0,
  "notification": {
    "layout": "",
    "title": "",
    "text": "Fetching location",
    "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": true,
  "schedulerEnabled": false,
  "trackingMode": 1,
  "odometer": 11576.0078125,
  "isFirstBoot": false,
  "didLaunchInBackground": false
}
╔═════════════════════════════════════════════
║ DEVICE SENSORS
╠═════════════════════════════════════════════
╟─ ✅  ACCELEROMETER: {Sensor name="icm4x6xx Accelerometer Non-wakeup", vendor="TDK-Invensense", version=291, type=1, maxRange=156.9064, resolution=0.0047884034, power=0.24, minDelay=2000}
╟─ ✅  GYROSCOPE: {Sensor name="icm4x6xx Gyroscope Non-wakeup", vendor="TDK-Invensense", version=291, type=4, maxRange=34.905556, resolution=0.001065233, power=0.57, minDelay=2000}
╟─ ✅  MAGNETOMETER: {Sensor name="ak0991x Magnetometer Non-wakeup", vendor="akm", version=20034, type=2, maxRange=4911.994, resolution=0.15, power=1.1, minDelay=10000}
╟─ ✅  SIGNIFICANT_MOTION: {Sensor name="sns_smd  Wakeup", vendor="qualcomm", version=1, type=17, maxRange=1.0, resolution=1.0, power=0.025, minDelay=-1}
╚═════════════════════════════════════════════ 

background-geolocationandroid.log

christocracy commented 3 years ago

Do you have a question?

erluxman commented 3 years ago

App gets location updates from this plugin when app is in foreground, when minimized, when swipe closed from recent menu and when device is rebooted.

What is the possibility of such occurance.. I will also uplo

Data uploads from Android.

https://user-images.githubusercontent.com/6260014/114874279-e6e4ec00-9e1b-11eb-9b8f-bbed34039c8e.mov

Data uploaded from iPhone

https://user-images.githubusercontent.com/6260014/114874095-b3a25d00-9e1b-11eb-9ef8-7c5b730a377c.mov

As you can see in the above videos, considering this timeline :


3:35 Closed all apps (iphone app,android app and sample app)
3:48 Opened all three apps
3:54 Closed all apps agan.  ( then drove for some time)
Took rest until 5:42 AM and started driving on motorbike
5:49 Rebooted device and unlocked it right after
5:56 Unlocked both devices again (as I didn’t hear debug sounds)- started hearing debug sound again.
6:06 Stopped.

Logs are uploaded to firestore only when app is in foreground or background but when app is closed or rebooted, it doesn't upload .. But at the same time the sample app from playstore is uploading data properly to http://tracker.transistorsoft.com/greenplay?device=33387&end=2021-4-15&start=2021-4-15

While looking into the logs , they are there even when app is closed from recent or rebooted. So I suspect It has something to do with location_uploader.dart what kind of code makes it possible to not be able to upload to firestore?

Is it compulsory for such logic to be in main.dart like the headless callback?

christocracy commented 3 years ago

Is it compulsory for such logic to be in main.dart like the headless callback?

Headless == terminated. If your Android app is terminated, then yes.

erluxman commented 3 years ago

Headless == terminated. If your Android app is terminated, then yes.

In that case any guess why is it not uploading in iOS even if the whole application is started in background?

christocracy commented 3 years ago

iOS has no such concept of "Headless". Headless is an Android-only mechanism.

When an iOS app is terminated, tracking resumes only after the device moves at least 200 meters. See API docs Config.stopOnTerminate for more information.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. You may also mark this issue as a "discussion" and I will leave this open.

stale[bot] commented 3 years ago

Closing this issue after a prolonged period of inactivity. Fell free to reopen this issue, if this still affecting you.