Closed lbdroid closed 1 year ago
Create basic foreground service like this (also adding the service to AndroidManifest.xml);
public class ForegroundService extends Service {
private static final String LOG_TAG = "Tracker Service";
private final String serviceChannelId = "tracker_detector_s";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
// runs first
super.onCreate();
Log.d(LOG_TAG, "Running onCreate()");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(serviceChannelId, "Nextcloud Service", NotificationManager.IMPORTANCE_NONE);
mChannel.setDescription("Tracker Detector Service");
notificationManager.createNotificationChannel(mChannel);
}
Notification newNotification =
new NotificationCompat.Builder(ForegroundService.this, serviceChannelId)
.setSmallIcon(android.R.drawable.ic_input_add)
.setContentTitle("Tracker-Service")
.setContentText("Keep gps working")
.build();
startForeground(88811, newNotification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// runs second
return START_STICKY;
}
}
Add this near the end of TrackingDetectorWorker.doWork():
val service = Intent(getApplicationContext(), ForegroundService::class.java)
getApplicationContext()!!.startForegroundService(service)
And rejigging ScanBluetoothWorker.doWork():
Timber.d("Scanning for bluetooth le devices stopped!. Discovered ${scanResultDictionary.size} devices")
if (SharedPrefs.useLocationInTrackingDetection && scanResultDictionary.size > 0) {
val lastLocation = locationProvider.getLastLocation()
if (lastLocation != null) {
// Location matches the requirement. No need to request a new one
location = lastLocation
Timber.d("Using last location")
} else {
//Getting the most accurate location here
locationProvider.getCurrentLocation { loc ->
this.location = loc
Timber.d("Updated to current location")
}
val fetchedLocation = this.waitForRequestedLocation()
Timber.d("Fetched location? ${fetchedLocation}")
}
}
The above makes location acquisition work infinitely better. The service doesn't have to do anything at all besides just sit there in the foreground in order to escape from the background location rate restrictions. The rejigging of ScanBluetoothWorker just avoids wasting power on finding a location if no bluetooth device was detected.
Hi, Yes we fixed this issue in the next version. Stay tuned for the update 😊
Also, support for opencellid key can be added to have more frequent location data but not GPS based, so to save battery
How would that be implemented? Is that part of Android's location access API?
No, I meant instead of the app getting location data only from GPS, it could also additionally/alternatively get location from opencellid api(if user has set an api key for it in the settings). Similar to how Find My Device(FMD) does it. Check screenshots.
@Sn0wfreezeDev I meant yes, it is part of Android's location access API but cell location would work only if user has GMS. For non-GMS users, having an option to use a third party like opencellid would be ideal.
Since AOSP 8, there are limitations placed on background location access for the supposed purpose of reducing battery consumption.
https://developer.android.com/about/versions/oreo/background-location-limits
In practice, background location access is very severely reduced to about 2-3 times per hour.
The easiest way to work around this limitation is to create a foreground service (see link above).
Power consumption on location access can be reduced by only requesting location after a tracking device is already detected. The current process in ScanBluetoothWorker is that first it begins a location request, THEN it begins scanning for trackers, and then it waits for the location request to complete and puts them together. I would propose that it first scans for trackers, then ONLY IF a tracker is detected, begin and wait for a location.