Search code examples
androidiosdartpermissionsflutter

Flutter: How do I listen to permissions real time


I am working on an app in which I want to continuously listen to location and battery permissions.

Sample scenario:

  1. The user opens the app
  2. Grants permission access
  3. Goes to settings and revokes the permissions
  4. Opens the app again
  5. The app displays a snackbar that informs the user that permission has been revoked.

I am a beginner and I am using the flutter-permissions-handler and the piece of code below shows my usage.

    _listenForLocationPermission() {
    Future<PermissionStatus> status = PermissionHandler()
        .checkPermissionStatus(PermissionGroup.locationWhenInUse);
    status.then((PermissionStatus status) {
      setState(() {
        _permissionStatus = status;
        if (_permissionStatus != PermissionStatus.granted) {
          _renderOfflineSnackbar('Offline');
        }
      });
    });
  }

Any advice on the above is appreciated.


Solution

  • I'm in the same boat and have found that this works

    You need to extend your class with WidgetsBindingObserver

    class _AppState extends State<App> with WidgetsBindingObserver {
      PermissionStatus _status;
      ...
      ...
    

    then add these methods to your class

    @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      // check permissions when app is resumed
      // this is when permissions are changed in app settings outside of app
      void didChangeAppLifecycleState(AppLifecycleState state) {
        if (state == AppLifecycleState.resumed) {
          PermissionHandler()
              .checkPermissionStatus(PermissionGroup.locationWhenInUse)
              .then(_updateStatus);
        }
      }
    

    My full code is below, but I've not included the build widget to keep it brief

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:permission_handler/permission_handler.dart';
    
    void main() => runApp(App());
    
    class App extends StatefulWidget {
      @override
      _AppState createState() => _AppState();
    }
    
    class _AppState extends State<App> with WidgetsBindingObserver {
      PermissionStatus _status;
    
      // check permissions
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addObserver(this);
        PermissionHandler() // Check location permission has been granted
            .checkPermissionStatus(PermissionGroup
                .locationWhenInUse) //check permission returns a Future
            .then(_updateStatus); // handling in callback to prevent blocking UI
      }
    
      @override
      void dispose() {
        WidgetsBinding.instance.removeObserver(this);
        super.dispose();
      }
    
      // check permissions when app is resumed
      // this is when permissions are changed in app settings outside of app
      void didChangeAppLifecycleState(AppLifecycleState state) {
        if (state == AppLifecycleState.resumed) {
          PermissionHandler()
              .checkPermissionStatus(PermissionGroup.locationWhenInUse)
              .then(_updateStatus);
        }
      }
    
    override
      Widget build(BuildContext context) {
        return MaterialApp(  
        ...
        ...
    }
    
    void _updateStatus(PermissionStatus status) {
        if (status != _status) {
          // check status has changed
          setState(() {
            _status = status; // update
          });
        } else {
          if (status != PermissionStatus.granted) {
            PermissionHandler().requestPermissions(
                [PermissionGroup.locationWhenInUse]).then(_onStatusRequested);
          }
          }
        }
      }
    
      void _askPermission() {
        PermissionHandler().requestPermissions(
            [PermissionGroup.locationWhenInUse]).then(_onStatusRequested);
      }
    
      void _onStatusRequested(Map<PermissionGroup, PermissionStatus> statuses) {
        final status = statuses[PermissionGroup.locationWhenInUse];
        if (status != PermissionStatus.granted) {
          // On iOS if "deny" is pressed, open App Settings
          PermissionHandler().openAppSettings();
        } else {
          _updateStatus(status);
        }
      }
    
    

    I hope this helps