Baseflow / flutter-geolocator

Android and iOS Geolocation plugin for Flutter
https://baseflow.com/
MIT License
1.24k stars 653 forks source link

[Bug]: F-droid builds fail because of google service dependencies #1481

Open Y0ngg4n opened 6 months ago

Y0ngg4n commented 6 months ago

Please check the following before submitting a new issue.

Please select affected platform(s)

Steps to reproduce

I am trying to build this Fdroid app:

Categories:
  - Navigation
  - Internet
  - Wissenschaft / Bildung
License: GPL-3.0-only
AuthorName: Yonggan
AuthorEmail: yonggan@obco.pro
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:
      - flutter@3.19.0
    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 ```dart 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? _positionStreamSubscription; StreamSubscription? _updatePositionStreamSubscription; bool listeningToPosition = false; Position? lastPosition; bool serviceEnabled = true; LocationPermission permission = LocationPermission.always; Future 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 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 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 checkPositionInCircle(WidgetRef ref, Position? position) async { if (position == null) return; List pois = ref.watch(poiProvider); List 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 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 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 ```console 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. ```
TimHoogstrate commented 6 months ago

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,

Y0ngg4n commented 6 months ago

@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

TimHoogstrate commented 6 months ago

Dear @Y0ngg4n,

Then, can you elaborate a bit more on the subject? Your issue is a bit unclear to me.

Kind regards,

Y0ngg4n commented 5 months ago

@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

Y0ngg4n commented 5 months ago

@TimHoogstrate is that helpfull?

rusty-snake commented 3 months ago

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'
}
Y0ngg4n commented 3 months ago

@rusty-snake thats exactly what i did but fdroid builds are still failing because the google library is still there