0

I am using location plugin to get user location in background.

The build of app is dependent on a future value where it first checks in initState if user is registered using a REST API, and poll location if user is registered or show Register button.

Below is relevant structure my code:


class HomePage extends StatefulWidget {
  const HomePage ({Key? key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  Location location = Location();

  Future<bool>? _registered;
  late bool _serviceEnabled;
  late PermissionStatus _permissionGranted;
  late LocationData _locationData;

  Future<bool> fetchUserInfo() async {
    // checks if user is registered
  }

  Future<LocationData?> setLocationPermissions() async {
    _serviceEnabled = await location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await location.requestService();
      if (!_serviceEnabled) {
        return null;
      }
    }

    _permissionGranted = await location.hasPermission();
    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await location.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return null;
      }
    }

    await location.changeSettings(interval: 30000);
    await location.enableBackgroundMode(enable: true);

    _locationData = await location.getLocation();
    return _locationData;
  }

  @override
  void initState() {
    setLocationPermissions().then((value) {
      _locationData = value!;
    }); //this is supposed to ask for location permissions

    // Fetch user details from server
    _registered = fetchUserInfo();

    location.onLocationChanged.listen((LocationData currentLocation) {
      // do more stuff
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Manager'),
      ),
      body: FutureBuilder(
        future: _registered,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return _buildWidget(screenSize); // widget function that returns either a 
                                             // Register button or Text "You are registered"
                                             // based on another value set in fetchUserInfo
          } else if (snapshot.hasError){
            Fluttertoast.showToast(msg: snapshot.error.toString());
            return const SizedBox();
          } else {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  CircularProgressIndicator(),
                ],
              ),
            );
          }
        }
      ),
    );
  }
}

When I open the app on release apk, if a user is not registered it simply renders the register button from _buildWidget. My expectation is that it should ask for location permission based on code in initState. However it doesn't. It was working fine if I don't use a FutureBuilder (here)

MohitC
  • 3,952
  • 1
  • 29
  • 49

1 Answers1

0

Possible problem is that widget build up is somehow over-riding the locations popup or its future never makes it to user interface due to some error in setpermissions initialization or some conflict with widget tree..

I fixed it by putting all the code inside initState in one common async function and setting the future of the future builder to this common function.

MohitC
  • 3,952
  • 1
  • 29
  • 49