Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 424
iprateekk Avatar asked Mar 31 '19 16:03

iprateekk


People also ask

How do you handle permissions in flutter?

Setup. While the permissions are being requested during runtime, you'll still need to tell the OS which permissions your app might potentially use. That requires adding permission configuration to Android- and iOS-specific files. Since version 4.4.0 this plugin is implemented using the Flutter 1.12 Android plugin APIs.

Where do I put user permissions in manifest in flutter?

Android. Add the permissions your app needs to the android/app/src/main/AndroidManifest. xml. Put the permissions in the manifest tag, infront of the application tag.


2 Answers

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

like image 130
Andrew Stevenson Avatar answered Sep 22 '22 20:09

Andrew Stevenson


Null safe code:

permission_handler: ^8.0.0+2

The idea is to check for the permission in the app's lifecycle callback when the state is resumed. Here's the minimal code to get you going.

class _FooPageState extends State<FooPage> with WidgetsBindingObserver {
  final Permission _permission = Permission.location;
  bool _checkingPermission = false;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance!.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed && !_checkingPermission) {
      _checkingPermission = true;
      _checkPermission(_permission).then((_) => _checkingPermission = false);
    }
  }

  Future<void> _checkPermission(Permission permission) async {
    final status = await permission.request();
    if (status == PermissionStatus.granted) {
      print('Permission granted');
    } else if (status == PermissionStatus.denied) {
      print('Permission denied. Show a dialog and again ask for the permission');
    } else if (status == PermissionStatus.permanentlyDenied) {
      print('Take the user to the settings page.');
    }
  }

  @override
  Widget build(BuildContext context) => Scaffold();
}
like image 42
CopsOnRoad Avatar answered Sep 23 '22 20:09

CopsOnRoad