Apri
Apri

Reputation: 1515

Flutter health permissions

I use the health package in my App to sync data between my app and Google Fit / Apple Health. So far I have only testet Apple Health and it works perfectly fine if I grant all the necessary permissions. But I found one weird thing and I can't figure out how to fix it. So far I have only implemented and tested the integration with Apple Health.

So, I check if the app has the permission to read or write a certain data type, and then I read it or write it to Apple Health. If the permission was granted and the read / write operation was successful, I want to present that to the user. If the permission was not granted, I also want to present that to the user, so he knows what went wrong. In the HealthFactory class of the package there is the requestAuthorization method that I call to check whether the user has permission or not. The behavior I expected was that, if the permission is not granted, the return value of that method is false if the permission is not granted. But instead, it is always true. Also, the methods getHealthDataFromTypes and writeHealthData don't really indicate whether the permission is granted or not.

I implemented a few methods to showcase that:

class TestScreen extends StatelessWidget {
  TestScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              child: Text("Health Permission"),
              onPressed: () async {
                final HealthFactory _health = HealthFactory();
                await Permission.activityRecognition.request();
                bool permission = await _health.requestAuthorization(
                  [HealthDataType.WEIGHT],
                  permissions: [HealthDataAccess.READ_WRITE],
                );
                print(permission);
              },
            ),
            ElevatedButton(
              child: Text("Read Data"),
              onPressed: () async {
                final HealthFactory _health = HealthFactory();
                DateTime untilDate = DateTime.now();
                DateTime fromDate = DateTime(1970);
                try {
                  List<HealthDataPoint> healthData =
                      await _health.getHealthDataFromTypes(
                    fromDate,
                    untilDate,
                    [HealthDataType.WEIGHT],
                  );
                  return print(healthData.toString());
                } on Exception catch (e) {
                  print(e.toString());
                  rethrow;
                }
              },
            ),
            ElevatedButton(
              child: Text("Write Data"),
              onPressed: () async {
                final HealthFactory _health = HealthFactory();
                try {
                  bool success = await _health.writeHealthData(
                    80,
                    HealthDataType.WEIGHT,
                    DateTime.now(),
                    DateTime.now(),
                  );
                  print(success);
                } on Exception catch (e) {
                  print(e.toString());
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

This is my test screen.

The first button requests READ_WRITE permission for the datatype WEIGHT. At the first call, this window pops up: Health Access When I click on "Don't Allow" in the top left corner, the permissions are NOT granted, but the method still returns true. If I go to the settings, no matter if I activate the permission or not, it always returns true.

The second button is supposed to read WEIGHT data from Apple Health. If the permission is granted, everything works fine. If the permission is NOT granted, it still "works", but jsut returns an empty list. This is pretty bad, because I can't indicate whether it failed or Apple Health just doesn't have any WEIGHT data.

The third button is supposed to write WEIGHT data into Apple Health. If the permission is granted, again, everthing works fine. If ther permission is NOT granted, the mehod returns false and doesn't write anything. This is already a better indicator than from the READ operation, but still, I can't indicate whether the permission wasn't granted or it was some other error.

So my question is: Is there any way to indicate at code level whether the permissions have been granted or not? I really need this to present to the user if the sync worked, and if not, why it didn't work.

Upvotes: 2

Views: 3611

Answers (2)

Vincent Jouanne
Vincent Jouanne

Reputation: 1

You are right, it seems like HealthKit do not allow us to access the permission status. I personally consider that the user did not toggled the permission if I can't get its steps over the past month:

  Future<bool> hasPermissionsOniOS() async {
    final now = DateTime.now();
    final lastMonth = DateTime(now.year, now.month - 1, now.day);
    final stepsOfLastMonth =
        await health.getTotalStepsInInterval(lastMonth, now);
    return stepsOfLastMonth != null;
  }

Upvotes: 0

DEFL
DEFL

Reputation: 1052

Please take a look at the documentation https://pub.dev/documentation/health/latest/health/HealthFactory/hasPermissions.html please also verify but on IOS it looks like it returns null. Apple protects this fields and the package returns null as Apple HealthKit will not disclose if READ access has been granted for a data type due to privacy concern, this method can only return null to represent an undertermined status, if it is called on iOS with a READ or READ_WRITE access.:

Upvotes: 0

Related Questions