cph-cachet / flutter-plugins

A collection of Flutter plugins developed by CACHET
551 stars 681 forks source link

[HEALTH 8.1.0] Error when request permission for HealthConnect #887

Closed 1ns4n33 closed 9 months ago

1ns4n33 commented 9 months ago

Device / Emulator and OS

Describe the bug

I'm getting errors when I try to request Health Connect permissions (I have already request to Google the permissions for HealthConnect for my App and got accepted).

WIth SDK 33: I have attached a screen to show where it crash, when I select the account it give me this error:

W/Parcel  (11639): Expecting binder but got null!
I/FLUTTER_HEALTH(11639): Access Denied!

While with SDK 34 I got another error, with this one it doesn't open any intent:

E/MethodChannel#flutter_health(18543): Failed to handle method call
E/MethodChannel#flutter_health(18543): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=androidx.activity.result.contract.action.REQUEST_PERMISSIONS (has extras) }
E/MethodChannel#flutter_health(18543):  at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2239)
E/MethodChannel#flutter_health(18543):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1878)
E/MethodChannel#flutter_health(18543):  at android.app.Activity.startActivityForResult(Activity.java:5589)
E/MethodChannel#flutter_health(18543):  at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:705)
E/MethodChannel#flutter_health(18543):  at android.app.Activity.startActivityForResult(Activity.java:5547)
E/MethodChannel#flutter_health(18543):  at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:686)
E/MethodChannel#flutter_health(18543):  at cachet.plugins.health.HealthPlugin.requestAuthorizationHC(HealthPlugin.kt:1684)
E/MethodChannel#flutter_health(18543):  at cachet.plugins.health.HealthPlugin.requestAuthorization(HealthPlugin.kt:1374)
E/MethodChannel#flutter_health(18543):  at cachet.plugins.health.HealthPlugin.onMethodCall(HealthPlugin.kt:1537)
E/MethodChannel#flutter_health(18543):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
E/MethodChannel#flutter_health(18543):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/MethodChannel#flutter_health(18543):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0(DartMessenger.java:322)
E/MethodChannel#flutter_health(18543):  at io.flutter.embedding.engine.dart.DartMessenger.$r8$lambda$2j2MERcK825A5j1fv5sZ7xB2Iuo(DartMessenger.java:0)
E/MethodChannel#flutter_health(18543):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(R8$$SyntheticClass:0)
E/MethodChannel#flutter_health(18543):  at android.os.Handler.handleCallback(Handler.java:958)
E/MethodChannel#flutter_health(18543):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/MethodChannel#flutter_health(18543):  at android.os.Looper.loopOnce(Looper.java:205)
E/MethodChannel#flutter_health(18543):  at android.os.Looper.loop(Looper.java:294)
E/MethodChannel#flutter_health(18543):  at android.app.ActivityThread.main(ActivityThread.java:8177)
E/MethodChannel#flutter_health(18543):  at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#flutter_health(18543):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
E/MethodChannel#flutter_health(18543):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
I/flutter (18543): PlatformException(error, No Activity found to handle Intent { act=androidx.activity.result.contract.action.REQUEST_PERMISSIONS (has extras) }, null, android.content.ActivityNotFoundException: No Activity found to handle Intent { act=androidx.activity.result.contract.action.REQUEST_PERMISSIONS (has extras) }
I/flutter (18543):  at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2239)
I/flutter (18543):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1878)
I/flutter (18543):  at android.app.Activity.startActivityForResult(Activity.java:5589)
I/flutter (18543):  at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:705)
I/flutter (18543):  at android.app.Activity.startActivityForResult(Activity.java:5547)
I/flutter (18543):  at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:686)
I/flutter (18543):  at cachet.plugins.health.HealthPlugin.requestAuthorizationHC(HealthPlugin.kt:1684)
I/flutter (18543):  at cachet.plugins.health.HealthPlugin.requestAuthorization(HealthPlugin.kt:1374)
I/flutter (18543):  at cachet.plugins.health.HealthPlugin.onMethodCall(HealthPlugin.kt:1
D/EGL_emulation(18543): app_time_stats: avg=327.76ms min=11.45ms max=12158.62ms count=39

To Reproduce

Install Health Connect (Beta), initialise it and then try to request some HealthDataType with Android 33 or 34

Screenshots

Screenshot_1706792818

Flutter doctor

Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, 3.16.9, on macOS 14.2 23C64 darwin-arm64, locale en-IT) [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [✓] Xcode - develop for iOS and macOS (Xcode 15.2) [✓] Chrome - develop for the web [✓] Android Studio (version 2023.1) [✓] VS Code (version 1.85.2) [✓] Connected device (4 available) ! Error: Browsing on the local area network for iPhone. Ensure the device is unlocked and attached with a cable or associated with the same local area network as this Mac. The device must be opted into Developer Mode to connect wirelessly. (code -27) [✓] Network resources

• No issues found!

Additional information

I have found another issue, for IOS the number of flights climber it's called 'FLIGHTS_CLIMBED' but for Android it's 'FLOORS_CLIMBED', the last one doesn't exists and if you try to request 'FLIGHTS_CLIMBER' it will crash.

This is how I request the permissions:

Future<bool> requestActivityRecognitionPermission() async {
  HealthFactory health = HealthFactory(useHealthConnectIfAvailable: true);

  if (Platform.isAndroid) {
    return await health
        .requestAuthorization(dataTypesAndroid,
            permissions: healthDataPermission)
        .then((value) {
      return value;
    });
  } else {
    return await health.requestAuthorization(dataTypesIOS);
  }
}

/// List of data types available on Android
const List<HealthDataType> dataTypesAndroid = [
  HealthDataType.ACTIVE_ENERGY_BURNED,
  HealthDataType.BODY_FAT_PERCENTAGE,
  HealthDataType.HEIGHT,
  HealthDataType.WEIGHT,
  HealthDataType.STEPS,
  HealthDataType.DISTANCE_DELTA,
  HealthDataType.WATER,
  HealthDataType.WORKOUT,
  // HealthDataType.FLOORS_CLIMBED
];

const List<HealthDataAccess> healthDataPermission = [
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ,
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ_WRITE,
  HealthDataAccess.READ_WRITE,
];

This is my actual Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jimtime.gabrielegusmeroli">
    <queries>
        <package android:name="com.google.android.apps.healthdata" />
        <intent>
            <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
        </intent>
    </queries>

    <uses-permission android:name="com.google.android.gms.permission.ADD_ID"/>

    <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>

    <uses-permission android:name="android.permission.health.WRITE_EXERCISE_ROUTE" />
    <uses-permission android:name="android.permission.health.WRITE_EXERCISE" />

    <uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED"/>
    <uses-permission android:name="android.permission.health.WRITE_ACTIVE_CALORIES_BURNED"/>

    <uses-permission android:name="android.permission.health.READ_BODY_FAT"/>
    <uses-permission android:name="android.permission.health.WRITE_BODY_FAT"/>

    <uses-permission android:name="android.permission.health.READ_HEIGHT"/>
    <uses-permission android:name="android.permission.health.WRITE_HEIGHT"/>

    <uses-permission android:name="android.permission.health.READ_WEIGHT"/>
    <uses-permission android:name="android.permission.health.WRITE_WEIGHT"/>

    <uses-permission android:name="android.permission.health.READ_STEPS"/>

    <uses-permission android:name="android.permission.health.READ_DISTANCE"/>
    <uses-permission android:name="android.permission.health.WRITE_DISTANCE"/>

    <uses-permission android:name="android.permission.health.READ_HYDRATION"/>
    <uses-permission android:name="android.permission.health.WRITE_HYDRATION"/>

    <uses-permission android:name="android.permission.health.READ_EXERCISE"/>
    <uses-permission android:name="android.permission.health.WRITE_EXERCISE"/>

    <uses-permission android:name="android.permission.health.WRITE_FLOORS_CLIMBED"/>
    <uses-permission android:name="android.permission.health.READ_FLOORS_CLIMBED"/>

    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.USE_FINGERPRINT"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
        android:label="JimTime"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
            </intent-filter>
        </activity>
        <activity
      android:name=".PermissionsRationaleActivity"
      android:exported="true">
            <intent-filter>
                <action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
            </intent-filter>
        </activity>

  <!-- For versions starting Android 14, create an activity alias to show the rationale
       of Health Connect permissions once users click the privacy policy link. -->
  <activity-alias
      android:name="ViewPermissionUsageActivity"
      android:exported="true"
      android:targetActivity=".PermissionsRationaleActivity"
      android:permission="android.permission.START_VIEW_PERMISSION_USAGE">
    <intent-filter>
      <action android:name="android.intent.action.VIEW_PERMISSION_USAGE" />
      <category android:name="android.intent.category.HEALTH_PERMISSIONS" />
    </intent-filter>
  </activity-alias>
    <!-- Those lines below are used to Schedule notification -->
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
        </intent-filter>
    </receiver>
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
    <!-- Don't delete the meta-data below.
            This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
    <meta-data
        android:name="flutterEmbedding"
        android:value="2" />
    </application>
</manifest>
pmagnuson commented 9 months ago

also having this issue. Exception trace below.

E/MethodChannel#flutter_health(18416): Failed to handle method call
E/MethodChannel#flutter_health(18416): java.lang.NullPointerException
E/MethodChannel#flutter_health(18416):  at cachet.plugins.health.HealthPlugin.requestAuthorizationHC(HealthPlugin.kt:1648)
E/MethodChannel#flutter_health(18416):  at cachet.plugins.health.HealthPlugin.requestAuthorization(HealthPlugin.kt:1374)
E/MethodChannel#flutter_health(18416):  at cachet.plugins.health.HealthPlugin.onMethodCall(HealthPlugin.kt:1537)
E/MethodChannel#flutter_health(18416):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:267)
E/MethodChannel#flutter_health(18416):  at io.flutter.embedding.engine.dart.DartMessenger.invokeHandler(DartMessenger.java:295)
E/MethodChannel#flutter_health(18416):  at io.flutter.embedding.engine.dart.DartMessenger.lambda$dispatchMessageToQueue$0$io-flutter-embedding-engine-dart-DartMessenger(DartMessenger.java:322)
E/MethodChannel#flutter_health(18416):  at io.flutter.embedding.engine.dart.DartMessenger$$ExternalSyntheticLambda0.run(Unknown Source:12)
E/MethodChannel#flutter_health(18416):  at android.os.Handler.handleCallback(Handler.java:958)
E/MethodChannel#flutter_health(18416):  at android.os.Handler.dispatchMessage(Handler.java:99)
E/MethodChannel#flutter_health(18416):  at android.os.Looper.loopOnce(Looper.java:230)
E/MethodChannel#flutter_health(18416):  at android.os.Looper.loop(Looper.java:319)
E/MethodChannel#flutter_health(18416):  at android.app.ActivityThread.main(ActivityThread.java:8893)
E/MethodChannel#flutter_health(18416):  at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#flutter_health(18416):  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
E/MethodChannel#flutter_health(18416):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
E/flutter (18416):  at cachet.plugins.health.HealthPlugin.requestAuthorizationHC(HealthPlugin.kt:1648)
E/flutter (18416):  at cachet.plugins.health.HealthPlugin.requestAuthorization(HealthPlugin.kt:1374)
E/flutter (18416):  at cachet.plugins.health.HealthPlugin.onMethodCall(HealthPlugin.kt:1537)
E/flutter (18416): #2      HealthFactory.requestAuthorization (package:health/src/health_factory.dart:150:32)
E/flutter (18416): #3      HealthProvider.initHealthProvider (package:dharmadr/services/health.dart:24:9)
onivas commented 9 months ago

I was having the same issue on Android 14, change from version 8.1.0 to 9.0.0 of the plugin and solve this issue (but a new one come up) :(

1ns4n33 commented 9 months ago

I was having the same issue on Android 14, change from version 8.1.0 to 9.0.0 of the plugin and solve this issue (but a new one come up) :(

Thank you for the reply, so we have to wait 🥲

phildharmadr commented 9 months ago

I was finally able to upgrade to 9.0.0. This resolved the issue for my.