flutter-geolocator
flutter-geolocator copied to clipboard
[Bug]: F-droid builds fail because of google service dependencies
Please check the following before submitting a new issue.
- [X] I have searched the existing issues.
- [X] I have carefully read the documentation and verified I have added the required platform specific configuration.
Please select affected platform(s)
- [X] Android
- [ ] iOS
- [ ] Linux
- [ ] macOS
- [ ] Web
- [ ] Windows
Steps to reproduce
I am trying to build this Fdroid app:
Categories:
- Navigation
- Internet
- Wissenschaft / Bildung
License: GPL-3.0-only
AuthorName: Yonggan
AuthorEmail: [email protected]
AuthorWebSite: https://obco.pro
WebSite: https://kifferkarte.org
SourceCode: https://github.com/Y0ngg4n/kifferkarte
IssueTracker: https://github.com/Y0ngg4n/kifferkarte/issues
Changelog: https://github.com/Y0ngg4n/kifferkarte/commits/master
Donate: https://liberapay.com/Yonggan/
AutoName: Kifferkarte
RepoType: git
Repo: https://github.com/Y0ngg4n/kifferkarte
AutoUpdateMode: Version
UpdateCheckMode: Tags
Builds:
- versionName: 1.0.3
versionCode: 6
commit: 1.0.3
output: build/app/outputs/flutter-apk/app-release.apk
srclibs:
- [email protected]
rm:
- ios
- linux
- macos
- test
- web
- windows
build:
- $$flutter$$/bin/flutter config --no-analytics
- $$flutter$$/bin/flutter packages pub get
- $$flutter$$/bin/flutter build apk
CurrentVersion: 1.0.3
CurrentVersionCode: 6
I have added
configurations.implementation {
exclude group: 'com.google.android.gms'
}
https://github.com/Y0ngg4n/kifferkarte/blob/master/android/app/build.gradle and i am never calling any service methods in the code
Expected results
I would expect that all unfree classes are not contained in the apk
Actual results
2024-04-14 10:51:00,940 INFO: Successfully built version 1.0.3 of pro.obco.kifferkarte from 31a4372793877e9ef7e257a2133c104910944052
2024-04-14 10:51:00,979 DEBUG: AXML contains a RESOURCE MAP
2024-04-14 10:51:00,979 DEBUG: Start of Namespace mapping: prefix 27: 'android' --> uri 54: 'http://schemas.android.com/apk/res/android'
2024-04-14 10:51:00,979 DEBUG: Checking build/pro.obco.kifferkarte/build/app/outputs/flutter-apk/app-release.apk
2024-04-14 10:51:00,980 DEBUG: AXML contains a RESOURCE MAP
2024-04-14 10:51:00,980 DEBUG: Start of Namespace mapping: prefix 27: 'android' --> uri 54: 'http://schemas.android.com/apk/res/android'
2024-04-14 10:51:00,981 INFO: Scanning APK with dexdump for known non-free classes.
2024-04-14 10:51:01,004 DEBUG: > /opt/android-sdk/build-tools/31.0.0/dexdump /tmp/tmpzgfce7pv/classes.dex
2024-04-14 10:51:01,425 DEBUG: > /opt/android-sdk/build-tools/31.0.0/dexdump /tmp/tmpzgfce7pv/classes2.dex
2024-04-14 10:51:02,540 DEBUG: Problem: found class 'com/google/android/gms/location/LocationCallback'
2024-04-14 10:51:02,542 DEBUG: Problem: found class 'com/google/android/gms/tasks/OnSuccessListener'
2024-04-14 10:51:02,558 DEBUG: Problem: found class 'com/google/android/gms/tasks/OnFailureListener'
2024-04-14 10:51:02,561 DEBUG: Problem: found class 'com/google/android/gms/location/FusedLocationProviderClient'
2024-04-14 10:51:02,562 DEBUG: Problem: found class 'com/google/android/gms/location/LocationRequest'
2024-04-14 10:51:02,606 DEBUG: Problem: found class 'com/google/android/gms/location/LocationSettingsRequest'
2024-04-14 10:51:02,627 DEBUG: Problem: found class 'com/google/android/gms/tasks/OnCompleteListener'
2024-04-14 10:51:02,635 CRITICAL: Found 7 problems in build/pro.obco.kifferkarte/build/app/outputs/flutter-apk/app-release.apk
2024-04-14 10:51:02,635 ERROR: Could not build app pro.obco.kifferkarte: Found blocklisted packages in final apk!
2024-04-14 10:51:02,635 DEBUG: Error encountered, stopping by user request.
https://gitlab.com/yonggan/fdroiddata/-/jobs/6620611451
Code sample
Code sample
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:geolocator/geolocator.dart';
import 'package:kifferkarte/map.dart';
import 'package:kifferkarte/overpass.dart';
import 'package:kifferkarte/provider_manager.dart';
import 'package:latlong2/latlong.dart';
import 'package:vibration/vibration.dart';
import 'package:point_in_polygon/point_in_polygon.dart' as pip;
class LocationManager {
final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;
StreamSubscription<Position>? _positionStreamSubscription;
StreamSubscription<Position>? _updatePositionStreamSubscription;
bool listeningToPosition = false;
Position? lastPosition;
bool serviceEnabled = true;
LocationPermission permission = LocationPermission.always;
Future<Position?> determinePosition() async {
await checkPermissions();
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
try {
Position currentPosition = await Geolocator.getCurrentPosition(
forceAndroidLocationManager: true,
timeLimit: Duration(seconds: 5),
);
lastPosition = currentPosition;
return lastPosition;
} catch (Exception) {
return lastPosition;
}
}
Future<bool> checkPermissions() async {
// // Test if location services are enabled.
// serviceEnabled = await Geolocator.isLocationServiceEnabled();
// if (!serviceEnabled) {
// // Location services are not enabled don't continue
// // accessing the position and request users of the
// // App to enable the location services.
// print('Location services are disabled.');
// Geolocator.openLocationSettings();
// }
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
// requesting permissions again (this is also where
// Android's shouldShowRequestPermissionRationale
// returned true. According to Android guidelines
// your App should show an explanatory UI now
print('Location permissions are denied');
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
print('Location permissions are denied');
permission = await Geolocator.requestPermission();
return false;
}
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
print(
'Location permissions are permanently denied, we cannot request permissions.');
return false;
}
return true;
}
Future<bool> startPositionCheck(WidgetRef ref, Function callUpdate) async {
bool wasNull = _positionStreamSubscription == null;
_positionStreamSubscription?.cancel();
_updatePositionStreamSubscription?.cancel();
if (!(await checkPermissions())) {
print("Check permission faileds");
return false;
}
LocationSettings locationSettings = LocationSettings(distanceFilter: 3);
LocationSettings updateLocationSettings =
LocationSettings(distanceFilter: 10);
if (Platform.isAndroid) {
print("Its android");
locationSettings =
AndroidSettings(forceLocationManager: true, distanceFilter: 10);
updateLocationSettings =
AndroidSettings(forceLocationManager: true, distanceFilter: 20);
}
var stream = _geolocatorPlatform.getPositionStream(
locationSettings: locationSettings);
_positionStreamSubscription = stream.listen((event) {
print("position via stream");
checkPositionInCircle(ref, event);
lastPosition = event;
ref.read(lastPositionProvider.notifier).set(event);
});
var updateStream = _geolocatorPlatform.getPositionStream(
locationSettings: updateLocationSettings);
_updatePositionStreamSubscription = updateStream.listen((event) {
callUpdate();
});
listeningToPosition = true;
if (wasNull) callUpdate();
return true;
}
void stopPositionCheck(WidgetRef ref) async {
_positionStreamSubscription?.cancel();
listeningToPosition = false;
}
Future<void> checkPositionInCircle(WidgetRef ref, Position? position) async {
if (position == null) return;
List<Poi> pois = ref.watch(poiProvider);
List<Way> ways = ref.watch(wayProvider);
Distance distance = const Distance();
bool inCircle = false;
bool inWay = false;
for (Poi poi in pois) {
if (poi.poiElement.lat != null &&
poi.poiElement.lon != null &&
distance.as(
LengthUnit.Meter,
LatLng(position.latitude, position.longitude),
LatLng(poi.poiElement.lat!, poi.poiElement.lon!)) <
radius) {
inCircle = true;
}
}
DateTime now = DateTime.now();
if (now.hour >= 7 && now.hour < 20) {
for (Way way in ways) {
List<pip.Point> bounds = way.boundaries
.map((e) => pip.Point(x: e.latitude, y: e.longitude))
.toList();
if (pip.Poly.isPointInPolygon(
pip.Point(x: position.latitude, y: position.longitude), bounds)) {
inWay = true;
}
}
}
bool currentInCircleState = ref.read(inCircleProvider);
bool currentInWayState = ref.read(inWayProvider);
print("currentInCirclestate $currentInCircleState");
print("inCircle $inCircle");
if (currentInCircleState != inCircle) {
if (inCircle) {
vibrate(ref);
await Future.delayed(const Duration(seconds: 1));
vibrate(ref);
} else {
vibrate(ref);
}
ref.read(inCircleProvider.notifier).set(inCircle);
}
if (currentInWayState != inWay) {
if (inWay) {
vibrate(ref);
await Future.delayed(const Duration(milliseconds: 500));
vibrate(ref);
await Future.delayed(const Duration(milliseconds: 500));
vibrate(ref);
} else {
vibrate(ref);
}
ref.read(inWayProvider.notifier).set(inWay);
} else {
print("Chek position in circle");
}
}
Future<void> vibrate(WidgetRef ref) async {
if (!ref.watch(vibrateProvider)) return;
bool? hasVibrator = await Vibration.hasVibrator();
if (hasVibrator != null && hasVibrator) {
Vibration.vibrate();
}
}
}
Screenshots or video
Screenshots or video demonstration
[Upload media here]
Version
11.0.0
Flutter Doctor output
Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.0, on NixOS 23.11 (Tapir) 6.1.79, locale de_DE.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✗] Chrome - develop for the web (Cannot find Chrome executable at google-chrome)
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Linux toolchain - develop for Linux desktop
[!] Android Studio (not installed)
[✓] Connected device (1 available)
[✓] Network resources
! Doctor found issues in 2 categories.
Dear @Y0ngg4n,
Thanks for filing this issue. According to our best knowledge we don't "officially" support F-droid. Furthermore, I don't fully understand your issue. To use the geolocator the google play services should be installed on the device. Could this be an indication of the error?
Kind regards,
@TimHoogstrate it should work without Google Play Services on android, because i use forceAndroidLocationManager always with true. And there was already a different issue that was closed because it was fixed: https://github.com/Baseflow/flutter-geolocator/issues/841 But it seems like it does not work anymore
Dear @Y0ngg4n,
Then, can you elaborate a bit more on the subject? Your issue is a bit unclear to me.
Kind regards,
@TimHoogstrate ok so for building apps for f-droid you have to remove all proprietary dependencies from the app. I tried that by adding the gradle exclude like described in the other issue. but it seems like there are still proprietary dependencies even if i dont use them and also exclude them in gradle like described in #841 So there should be an option to exclude all proprietary dependencies for fdroid builds. as described in #841 it should work with the gradle exclude but as you can see in the gitlab build there are still google service dependencies in the build even when i exclude them
@TimHoogstrate is that helpfull?
According to our best knowledge we don't "officially" support F-droid.
https://pub.dev/documentation/geolocator/latest/geolocator/AndroidSettings/forceLocationManager.html
To exclude Google mobile services from your app (for example because you want to publish your app to the F-Droid app store) you can add the following code to your android/app/build.gradle file:
configurations.implementation { exclude group: 'com.google.android.gms' }
@rusty-snake thats exactly what i did but fdroid builds are still failing because the google library is still there