transistorsoft / flutter_background_geolocation

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

We are getting crashes in prod like ForegroundServiceStartNotAllowedException in Android 12 & SQLiteCantOpenDatabaseException in android 11 (Xiaomi phone) #748

Closed Intellitrack2017 closed 4 months ago

Intellitrack2017 commented 2 years ago

Your Environment

Plugin config:

`void initState() { WidgetsBinding.instance.addObserver(this); _enabled = false;

//// // 1. Listen to events (See docs for all 12 available events). //

// Fired whenever a location is recorded bg.BackgroundGeolocation.onLocation((bg.Location location) { print("Locatiom $location");

});

// Fired whenever the plugin changes motion-state (stationary->moving and vice-versa) bg.BackgroundGeolocation.onMotionChange((bg.Location location) { // print(location); print("Locatiom $location");

});

bg.BackgroundGeolocation.onProviderChange((bg.ProviderChangeEvent event) { print('[Location Test App] - $event'); });

configFlutterBackGroundService();

}

configFlutterBackGroundService() async { SharedPreferences prefs = await SharedPreferences.getInstance();

////
// 2.  Configure the plugin
//
bg.BackgroundGeolocation.ready(bg.Config(
  // url: Apis.BASEURL + Apis.locations,
  // autoSync: true,
  // deferTime: 3000,
  desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
  distanceFilter: 0,
  locationUpdateInterval: 3000,
  autoSyncThreshold: 5,
  batchSync: true,
  reset: true,
  enableHeadless: true,
  stopOnTerminate: false,
  foregroundService: true,
  // isMoving: true,
  startOnBoot: true,
  heartbeatInterval: 60,
  debug: false,

  // startOnBoot: true,
  // maxBatchSize: 20,
  // headers: {
  //   "Content-Type": "application/json",
  //   "Authorization": 'Bearer ${prefs.getString(Globals.jws_token)}',
  // },
  // params: {
  //   'organizationId': prefs.getString(Globals.organizationId),
  //   'userId': prefs.getString(Globals.userIdPrefKey)
  // },
  locationsOrderDirection: "DESC",
  // maxDaysToPersist: 14
)).then((bg.State state) {
  if (!state.enabled) {
    ////
    // 3.  Start the plugin.
    //
    _enabled = state.enabled;
    checkBatteryOptimization();
  }
});

}

callStartServiceInNAtive() async {

//// // 3. Start the plugin. // bg.BackgroundGeolocation.start().then((bg.State state) { print('[start] success started $state'); _enabled = state.enabled; // To modify config after #ready has been executed, use #setConfig bg.BackgroundGeolocation.setConfig(bg.Config( isMoving: true, )).then((bg.State state) { bg.BackgroundGeolocation.sync(); }); }).catchError((error) { print('[start] starting failed ERROR: $error'); });

}

callStopServiceInNative() async {

if (_enabled) { bg.BackgroundGeolocation.stop() .then((bg.State state) => {

bg.BackgroundGeolocation.setOdometer(0.0)

}) .catchError((error) { print('[stop] stoping failed ERROR: $error'); }); } }`

Expected Behavior

We should not get any crashes in the production

Actual Behavior

We are getting 2 crashes in a production app

Crash 1:

Fatal Exception: android.app.ForegroundServiceStartNotAllowedException: startForegroundService() not allowed due to mAllowStartForeground false: service com.affluence.clu/com.transistorsoft.locationmanager.service.LocationRequestService at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:54) at android.app.ForegroundServiceStartNotAllowedException$1.createFromParcel(ForegroundServiceStartNotAllowedException.java:50) at android.os.Parcel.readParcelable(Parcel.java:3379) at android.os.Parcel.createExceptionOrNull(Parcel.java:2466) at android.os.Parcel.createException(Parcel.java:2455) at android.os.Parcel.readException(Parcel.java:2438) at android.os.Parcel.readException(Parcel.java:2380) at android.app.IActivityManager$Stub$Proxy.startService(IActivityManager.java:6103) at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1851) at android.app.ContextImpl.startForegroundService(ContextImpl.java:1827) at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:789) at com.transistorsoft.locationmanager.service.AbstractService$a.run(AbstractService.java:10) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:233) at android.os.Looper.loop(Looper.java:344) at android.app.ActivityThread.main(ActivityThread.java:8204) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)

Crash 2:

Caused by android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 14 SQLITE_CANTOPEN): , while compiling: PRAGMA journal_mode at android.database.sqlite.SQLiteConnection.nativePrepareStatement(SQLiteConnection.java) at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1045) at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:788) at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:405) at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:335) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:258) at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:205) at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:505) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206) at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:198) at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:918) at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:898) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:762) at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:751) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:373) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316) at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:4) at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:4) at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:2) at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java) at androidx.work.impl.model.SystemIdInfoDao_Impl.getWorkSpecIds(SystemIdInfoDao_Impl.java:9) at androidx.work.impl.background.systemjob.SystemJobScheduler.reconcileJobs(SystemJobScheduler.java:20) at androidx.work.impl.utils.ForceStopRunnable.cleanUp(ForceStopRunnable.java:11) at androidx.work.impl.utils.ForceStopRunnable.forceStopRunnable(ForceStopRunnable.java) at androidx.work.impl.utils.ForceStopRunnable.run(ForceStopRunnable.java:31) at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:2) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923)

christocracy commented 2 years ago

See CHANGELOG and update to latest version.

christocracy commented 2 years ago

I've pushed a release-candidate to branch release-4.7.0. This is a major refactor in support of Android 12.

Please try it out:

dependencies
  flutter_background_geolocation:
    git:
      url: https://github.com/transistorsoft/flutter_background_geolocation
      ref: release-4.7.0

4.7.0 — Unreleased

ozzy1873 commented 2 years ago

This breaks my app on Android 12. The previous version of the plugin still works on Android 12.

1) The plugin is configured to run as a foreground service. 2) The user starts location services by clicking a button. 3) The user shuts the screen off and leaves the phone stationary for 5 minutes. 4) The location services notification turns off. 5) The user starts moving again, but location services notification does not turn back on. Since this is running as a foreground service, it is still in use and should resume location updates.

bg.Config _getBgConfig() { return bg.Config( reset: true, desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH, distanceFilter: 5.0, preventSuspend: true, isMoving: true, stopOnTerminate: true, stopOnStationary: false, startOnBoot: false, stopTimeout: 5, persistMode: bg.Config.PERSIST_MODE_NONE, foregroundService: true, locationAuthorizationRequest: 'WhenInUse', ); }

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" />
christocracy commented 2 years ago

That’s the correct behaviour. Location-services cannot be initiated in the background with WhenInUse. If you let Config.stopTimeout expire, the plugin enters the stationary state and turns off location-services.

your app must return to the foreground to re-initiate location-services (ie .changePace(true))

christocracy commented 2 years ago

Using WhenInUse doesn’t come without consequences.

ozzy1873 commented 2 years ago

So, the only way to prevent location services from stopping in this scenario is to set stopTimeout to a really large value?

christocracy commented 2 years ago

That’s correct.

ozzy1873 commented 2 years ago

Can you give us an idea of the battery impact when setting stopTimeout to a really large value?

christocracy commented 2 years ago

And you will likely want to use a sane value.

using a value of hundreds of hours would likely not be desirable to your end-user and his/her battery should they forget to launch your app and perform the action which results in .stop() / .changePace(false).

christocracy commented 2 years ago

Can you give us an idea of the battery impact

Try it and see. Let it run in that state over night.

ozzy1873 commented 2 years ago

Will do, thanks.

stale[bot] commented 2 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.

github-actions[bot] commented 4 months ago

This issue was closed because it has been inactive for 14 days since being marked as stale.