Basel-525k / geofence_foreground_service

Apache License 2.0
8 stars 7 forks source link

Android listens to location in a Foreground Service #10

Open orkun1675 opened 3 months ago

orkun1675 commented 3 months ago

I was trying to understand why this plugin needs to show a notication on Android. Because per Android Geofencing documentation the app doesn't need to be running in the foreground to receive geofence events. See: https://developer.android.com/develop/sensors-and-location/location/geofencing#HandleGeofenceTransitions

I saw that the plugin starts a foreground service and requests location updates from the system: https://github.com/Basel-525k/geofence_foreground_service/blob/ff352619eb487dcc304062ec373cd35fdea2d918/android/src/main/kotlin/com/f2fk/geofence_foreground_service/GeofenceForegroundService.kt#L44-L52

Is this neccesary? Wouldn't the geofence be triggered by the system without this foreground location listener?

Basel-525k commented 3 months ago

You’re correct that the geofences are registered with the system and that the system triggers them. Ideally, the apps interested in these geofences should respond accordingly. However, if the app is not running—say, if it has been killed—the system will still send geofence signals, but there won’t be any app to handle them.

To ensure proper handling of geofence events, the app’s service needs to be running. If it isn’t, the system-generated geofence signals won't be processed.

This is the way I found working with Flutter at least, if there is a better way to handle this (as to turn the Flutter side on when receiving the event) then it would be a great addition to the plugin!

Note: having the service in the foreground makes it less likely to be killed by the system when the system is in need of resources

orkun1675 commented 1 month ago

Hi @Basel-525k, I needed a simpler geofencing solution that does not rely on foreground services so I took a week to develop native_geofence.

Please take a look. Curios to what you think. Would be great to collaborate on that plugin as well if you have a use-case for it. Note that I am yet to battle test it.

vadrian89 commented 4 weeks ago

@orkun1675 I've also been working on a geofence plugin that does not rely on foreground service, but ended up using this plugin.

The issue I've been hit with is that the geofence client is unreliable, at least on Android. Didn't even started on iOS.

What happened, in my testing, was that if the location wasn't being actively used the geofence events were not getting triggered. Tested it on multiple devices and emulators. It was like the geofencing client from google play did not work unless something was constantly monitoring the location of the device.

So, if you need to have reliable geofencing on Android, a foreground service is needed. Keep in mind, that with each new OS version, more and more restrictions are being set up. So even if the geofencing events are working at the moment without foreground service, it might become impossible in the next Android version.

You can see my work in progress at: https://github.com/vadrian89/flutter_background_geofence

orkun1675 commented 4 weeks ago

Hi @vadrian89 thanks for reaching out!

Tested it on multiple devices and emulators. It was like the geofencing client from google play did not work unless something was constantly monitoring the location of the device.

This is partially true per my testing. See https://pub.dev/packages/native_geofence#known-issues.

I was not able to get Android to trigger Geofence events in the emulator without using a second app like Maps to poll for GPS. However, in my daily testing for https://chunkytofustudios.com/destiwake/ I do see the Geofence trigger on physical devices when I approach a transit stop, about 80% of the time. It is not perfect, but we cannot ask our consumers to allow us to poll for GPS constantly in the background for a B2C app like this one.

My IRL tests were performed on Pixel 8 and Pixel 4A, which are known to be pretty reliable devices per https://dontkillmyapp.com/, so maybe that helped?

I have found iOS to be much more reliable, no issues so far.


How do you justify running a foreground service constantly? What kind of battery impact does it have?

Please do let me know how this pans out for you.

vadrian89 commented 3 weeks ago

I tested on 3 devices: a OnePlus Nord 3, Xiaomi Poco X3 running LineageOS and a Xiaomi Redmi Note 8 Pro None triggered, while in background, while on foot for a 100-120m radius. The Xiaomi Poco triggered the exit event after I left the city, as I have forgotten to remove the geofence. It seemed that triggered correctly when I looked at the hour of the notification.

but we cannot ask our consumers to allow us to poll for GPS constantly in the background for a B2C app like this one.

I agree that it's not ok for us to overuse the device but the geofencing is done by the system and hoped for more reliability.

My use case is for a an app which is used by companies field workers and needs to be 100% reliable.

I also think that we can coordinate to develop a more flexible plugin which would allow both (or multiple) use cases.

orkun1675 commented 3 weeks ago

I tested on 3 devices

To clarify, did you test using geofence_foreground_service or native_geofence or flutter_background_geofence?

We've also realized that even an OEM as big as Samsung tends to cut corners to reduce battery usage; such as killing our transit tracking apps foreground service, which is providing a critical service to the user.

My use case is for a an app which is used by companies field workers and needs to be 100% reliable.

I see, it sounds like a foreground service is justifiable in that scenario.

I also think that we can coordinate to develop a more flexible plugin which would allow both (or multiple) use cases.

The only delta between what native_geofence offers and what you need seems to be "a foreground service that polls for location every X minutes"; is that right? If so, I think native_geofence can be expanded to support that.

vadrian89 commented 3 weeks ago

To clarify, did you test using geofence_foreground_service or native_geofence or flutter_background_geofence?

flutter_background_geofence

After I realized I needed a foreground service I decided to look to what the community has to offer and, if needed, contribute to them.