10
votes

I'm building my first Flutter application and I've run into a bit of an async issue.

When my application executes I'd like it to ask for permissions and wait until they are granted. My main() function looks like this:

import 'permission_manager.dart' as Perm_Manager;

void main() async
{
  //Ensure valid permissions
  Perm_Manager.Permission_Manager pm = Perm_Manager.Permission_Manager();
  var res = await pm.get_permissions();
  print(res);

  return runApp(MyApp());
} 

The Permission Manager class' get_permissions() function uses the Flutter Simple Permissions package to check and ask for permissions.

import 'package:simple_permissions/simple_permissions.dart';
import 'dart:io' as IO;
import 'dart:async';

class Permission_Manager {
  /* Get user permissions */

  Future<bool> get_permissions() async
  {
    //Android handler
    if (IO.Platform.isAndroid)
    {
        //Check for read permissions
        SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
        {
          //If granted
          if (result)
            return true;

          //Otherwise request them
          else
          {
            SimplePermissions.requestPermission(Permission.ReadExternalStorage)
            .then((result)
            {
              // Determine if they were granted
              if (result == PermissionStatus.authorized)
                return true;
              else
                IO.exit(0); //TODO - display a message
            });
          }
        });
    }

    else
      return true;
  }
}

When I run the application it does not wait for the function to complete as intended and prints the value of "res" before the Future is updated.

Launching lib\main.dart on Android SDK built for x86 in debug mode...
Built build\app\outputs\apk\debug\app-debug.apk.
I/SimplePermission(15066): Checking permission : android.permission.READ_EXTERNAL_STORAGE
I/flutter (15066): null
I/SimplePermission(15066): Requesting permission : android.permission.READ_EXTERNAL_STORAGE

The Future returns a value midway through the function! Does anyone know what I'm doing wrong?

2

2 Answers

16
votes

To await something you have to call the await keyword on a future instead of .then

final result = await future;
// do something

instead of

future.then((result) {
  // do something
});

If you really want to use .then then you can await the generated future:

await future.then((result) {
  // do something
});

Just ensure that when using nested asynchronous calls that the async keyword is used on each:

await future.then((result) async{
    // do something
    await future.then((result_2) {
       // do something else
    });
});
-1
votes

Got it working. The issue seems to be resolved using a Completer:

import 'package:simple_permissions/simple_permissions.dart';
import 'dart:io' as IO;
import 'dart:async';

class Permission_Manager {
  /* Get user permissions */

  final Completer c = new Completer();

  Future get_permissions() async
  {

    //Android handler
    if (IO.Platform.isAndroid)
    {
        //Check for read permissions
        SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
        {
          //If granted
          if (result)
          {
            c.complete(true);
          }
          //Otherwise request them
          else
          {
            SimplePermissions.requestPermission(Permission.ReadExternalStorage).then((result)
            {
              // Determine if they were granted
              if (result == PermissionStatus.authorized)
              {
                c.complete(true);
              }
              else
              {
                IO.exit(0); //TODO - display a message
              }
            });
          }
        });
    }

    else
    {
      c.complete(true);
    }

    return c.future;
  }

}