Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Crash on permission denied - Release IOS only #1631

Closed
3 of 8 tasks
MilanMeurrens opened this issue Jan 28, 2025 · 1 comment
Closed
3 of 8 tasks

[Bug]: Crash on permission denied - Release IOS only #1631

MilanMeurrens opened this issue Jan 28, 2025 · 1 comment

Comments

@MilanMeurrens
Copy link

Please check the following before submitting a new issue.

Please select affected platform(s)

  • Android
  • iOS
  • Linux
  • macOS
  • Web
  • Windows

Steps to reproduce

  1. I've implemented the LocationProvider just like in the example on the package homepage.
  2. When running locally, on an IOS emulator, it works as expected. Both when accepting and denying the location permission.
  3. When running on an IOS device, in a signed production environment (release), it crashes the app on denying the location permission. It works fine on Android.

The only thing I do differently is throwing an error and wrapping it with a try-catch instead of returning a Future.error. I tried to debug but it doesn't throw any error messages that I could tell.

// Example from package homepage
import 'package:geolocator/geolocator.dart';

Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      return Future.error('Location permissions are denied');
    }
  }
  
  if (permission == LocationPermission.deniedForever) {
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  return await Geolocator.getCurrentPosition();
}

Expected results

Don't crash on denying location permission (IOS, signed release build only)

Actual results

Crashes on denying location permission (IOS, signed release build only). Once denied, the app crashes every time the determinePosition function is called.

Code sample

Code sample
// Example from package homepage
import 'package:geolocator/geolocator.dart';

Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      return Future.error('Location permissions are denied');
    }
  }
  
  if (permission == LocationPermission.deniedForever) {
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  return await Geolocator.getCurrentPosition();
}

Screenshots or video

Screenshots or video demonstration

[Upload media here]

Version

13.0.2

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.27.1, on macOS 14.3 23D56 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.2)
[✓] VS Code (version 1.96.1)
[✓] Connected device (4 available)
[✓] Network resources

• No issues found!
@MilanMeurrens
Copy link
Author

In the meantime, I was able to resolve the issue. It's a bit vague, but the problem was that I refactored this code into separate functions that caused the error.

I'm not 100% sure, but it seems like the likely cause of the crash is that iOS release builds handle method calls differently with optimizations enabled. When the permission request is in a separate function, the compiler might optimize it in a way that affects the timing of the permission dialog presentation.

So this code works fine

// Example from package homepage
import 'package:geolocator/geolocator.dart';

Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    return Future.error('Location services are disabled.');
  }

  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      return Future.error('Location permissions are denied');
    }
  }
  
  if (permission == LocationPermission.deniedForever) {
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  return await Geolocator.getCurrentPosition();
}

But this code crashes

// Example from package homepage
import 'package:geolocator/geolocator.dart';

Future<Position> _determinePosition() async {
  bool serviceEnabled;
  LocationPermission permission;

  serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
    return Future.error('Location services are disabled.');
  }
  
  // Separate function
 checkAndRequestPermission();

  if (permission == LocationPermission.deniedForever) {
    return Future.error(
      'Location permissions are permanently denied, we cannot request permissions.');
  } 

  return await Geolocator.getCurrentPosition();
}

Future<void> checkAndRequestPermission() {
  permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
    permission = await Geolocator.requestPermission();
    if (permission == LocationPermission.denied) {
      return Future.error('Location permissions are denied');
    }
  }
}

I had the same issue with the mobile_scanner package. This was solved by using the permission_handler to handle the camera permission request as it is baked into the mobile scanner code and couldn't be fixed.

Hope anyone can give some more conclusive insights! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant