Search code examples
fluttergps

Problems with gps and icon color change


I need the permission to use the gps to appear, for some reason it doesn't appear here, if the gps is activated the icon turns green and if the gps is turned off the icon will turn red, but without success. Soon it is not informing the address of the user also. I'll share the code:

    class AppBarCustom extends StatefulWidget {
  const AppBarCustom({Key? key}) : super(key: key);

  @override
  State<AppBarCustom> createState() => _AppBarCustomState();
}

class _AppBarCustomState extends State<AppBarCustom> {
  late SharedPreferences prefs;
  String address = 'Loanding...';
  double currentKm = 0;
  StreamSubscription<Position>? _positionStreamSubscription;

  @override
  void initState() {
    super.initState();
    initSharedOreferences();
    checkGpsStatusOnLoad();
    getLocationData();
  }

  Future<void> initSharedOreferences() async {
    prefs = await SharedPreferences.getInstance();
  }

  Future<void> checkGpsStatusOnLoad() async {
    LocationPermission permission = await Geolocator.checkPermission();

    if (permission == LocationPermission.denied) {
      setState(() {
        Provider.of<GpsStatusProvider>(context, listen: false)
            .setGpsActive(false);
      });
    } else {
      bool serviceEnabled = await Geolocator.isLocationServiceEnabled();

      if (!serviceEnabled) {
        setState(() {
          Provider.of<GpsStatusProvider>(context, listen: false)
              .setGpsActive(false);
        });
      } else {
        setState(() {
          Provider.of<GpsStatusProvider>(context, listen: false)
              .setGpsActive(true);
        });
      }
    }
  }

  Future<void> getLocationData() async {
    try {
      Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high,
      );
      List<Placemark> placemarks = await placemarkFromCoordinates(
        position.latitude,
        position.longitude,
      );
      Placemark placemark = placemarks.first;
      String streetName = placemark.thoroughfare ?? 'N/A';
      double? km = position.speed;

      setState(() {
        address = 'Street: $streetName';
        currentKm = km;
      });
    } catch (e) {
      if (kDebugMode) {
        print('Erro: $e');
      }
    }
  }

  @override
  void dispose() {
    super.dispose();
    _positionStreamSubscription?.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return Consumer<GpsStatusProvider>(
      builder: (context, gpsStatusProvider, _) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            const Spacer(),
            Text(
              'Street: $address',
              style: const TextStyle(fontSize: 15),
            ),
            const Spacer(),
            Text(
              'Km: ${currentKm.toStringAsFixed(3)}',
              style: const TextStyle(fontSize: 15),
            ),
            const Spacer(),
            CircleAvatar(
              radius: 13,
              backgroundColor: gpsStatusProvider.isGpsActive
                  ? Colors.green
                  : Colors.red,
              child: const Icon(
                Icons.gps_fixed,
                color: Colors.white,
                size: 20,
              ),
            ),
          ],
        );
      },
    );
  }
}

this is the provider that is used:

class GpsStatusProvider with ChangeNotifier {
  bool _isGpsActive = false;
  late StreamController<bool> _gpsActiveController;

  Stream<bool> get isGpsActiveStream => _gpsActiveController.stream;

  GpsStatusProvider() {
    _gpsActiveController = StreamController<bool>.broadcast();
  }

  bool get isGpsActive => _isGpsActive;

  void setGpsActive(bool isActive) {
    _isGpsActive = isActive;
    _gpsActiveController.add(isActive);
    notifyListeners();
  }

  @override
  void dispose() {
    _gpsActiveController.close();
    super.dispose();
  }
}

Solution

  • You haven't started listening to GpsStatusProvider notify listeners to stream. Update your initState method to listen to the stream.

    @override
    void initState() {
      super.initState();
      initSharedOreferences();
      checkGpsStatusOnLoad();
      getLocationData();
    
      // Start listening to GPS status changes
      Provider.of<GpsStatusProvider>(context, listen: false)
          .isGpsActiveStream
          .listen((isActive) {
        setState(() {
          // Update UI based on isActive
        });
      });
    }