Closed LeonNissen closed 6 months ago
Please read the documentation for setting up the project. You may have missed setting up your AndroidManifest.xml
configurations.
"Thank you for your response! I've double-checked the configuration in AndroidManifest.xml
, but the issue persists. For reference, I initiated a brand-new expo project and strictly followed the Get started guide.
Here is my AndroidManifest.xml
for further reference:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.health.READ_ACTIVE_CALORIES_BURNED"/>
<queries>
<intent>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"/>
</intent>
</queries>
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme">
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
<meta-data android:name="expo.modules.updates.EXPO_SDK_VERSION" android:value="49.0.0"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait">
<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>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="com.test.hctest"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
</application>
</manifest>
Is this just happening on Android 14?
Yes the issue occurs on Android 14 only. I've tested it with the emulator (API 34) and a physical device (Pixel 6 Pro). Android 13 (with the HealthConnect app) does work fine.
Try submitting the issue in Google's Issue Tracker and see if they have answer for it:
https://issuetracker.google.com/u/1/issues?q=status:open%20componentid:1232764&s=created_time:desc
Same issue for me when I run on Android 14
Found the migration plan here, hopefully this may help. https://developer.android.com/health-and-fitness/guides/health-connect/migrate/migrate-from-android-13-to-14
Hello, I managed to fix it by adjusting the Intent action for Android 14 on the native side. In HealthConnectManager.kt
, in the requestPermission
function, replace the intent declaration with this
val intent = if(Build.Version.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
Intent("android.health.connect.action.MANAGE_HEALTH_PERMISSIONS")
} else {
HCPermissionManager(providerPackageName).healthPermissionContract.createIntent(applicationContext, latestPermissions!!)
}
Also, add this to your AndroidManifest.xml
<activity-alias>
android:name="AndroidURationaleActivity"
android:exported="true"
android:targetActivity=".nameOfYourActivity"
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>
I am pretty sure, It still misses something but I am not very familiar with native Android development.
@matinzd What do you think about the solution of @PopJoestar? Is it suitable for a PR?
Hi
I reviewed the code, and it appears that this issue should not occur. Creating an intent should ideally be managed through the Google Health Connect.
I recommend following the document here and checking if you encounter any errors after making these modifications, without altering the underlying structure: https://developer.android.com/health-and-fitness/guides/health-connect/migrate/migrate-from-android-13-to-14#testing-apis-with-sdk
@LeonNissen
We're hit by the same issue. I've tried this solution and while it does prevent the crash, it simply opens Health Connect for us, and does not request permission. While the issue should not occur, it definitely does occur here.
I've tried the same fix as @antontanderup — it does prevent the phone from crashing, but we don't get to actually authenticate with Home Connect.
The library works great on Android 13, but we get that crash every time on Android 14.
Hi @antontanderup and @fredefl,
I was able to implement the solution suggested by @PopJoestar.
Yes you were right, when using the Intent android.health.connect.action.MANAGE_HEALTH_PERMISSIONS
the HealthConnect app will present all apps and their permissions. However, a hot fix for this would be to just select the app in this menu, allow the specific (or all) permissions and return to the app.
Thereafter the app is able to access HealthConnect's data.
However, I think we would need a different intent but I'm unfortunately no android developer. Additionally, I agree with @matinzd's answer:
I reviewed the code, and it appears that this issue should not occur. Creating an intent should ideally be managed through the Google Health Connect.
I'm holding off on updating this library until Google releases a stable version. We'll wait for that to ensure it's reliable. In the meantime, you're welcome to fork the project and customize it, or send a pull request.
I got the same crash issue on android 14. if you any solution for this crash issue. please help me on this thanks in advance
Came across this fix for a flutter plugin today. Dont have time to dig into this issue right now but I will circle back if its not resolved.
https://github.com/cph-cachet/flutter-plugins/issues/800
I believe this is the specific fix https://github.com/cph-cachet/flutter-plugins/pull/834/files#diff-f176f1231d82c07449b7bef3ffef63652c4704978f2ae846cac7259ff43a79ffR82-R91
Waiting for google to be stable before modifying is a good idea. Could also be forever haha
@LeonNissen it looks like you have a minimal expo android project/repo with the temporary fix that you implemented, do you mind sharing that minimal reproduction with us so we can see exactly how you implemented the fix?
@seanblonien sure thing! I've pushed it into a new repo: https://github.com/LeonNissen/test-hc/tree/main
Most important, you need to follow @PopJoestar's answer: https://github.com/matinzd/react-native-health-connect/issues/50#issuecomment-1782411647
The actual fix for react-native-health-connect
can be found here:
https://github.com/LeonNissen/test-hc/blob/587d780301b7cade3b496cabb396d516f82fe2c7/node_modules/react-native-health-connect/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt#L79
@LeonNissen Ah perfect, thank you for sharing, it helps a lot!
EDIT: nevermind it doesn't seem to work with health permissions 😢
I also discovered a JS-only workaround without changing internal package implementations (cause I had no idea how to persist node_modules
changes for my CI environment) -- use the react-native
PermissionsAndroid
module to get the permissions yourself, like so:
import {PermissionsAndroid} from 'react-native';
import {initialize, readRecords} from 'react-native-health-connect';
// ...
const isInitialized = await initialize(); // this is still needed for readRecords to work
if (!isInitialized) {
// handle
}
const permissionStatus = await PermissionsAndroid.request('android.permission.health.READ_STEPS' as Permission, {
title: 'Steps Permission',
message: 'App requires access to your step data for XYZ feature',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
});
const isGrantedStepsPermission = permissionStatus === PermissionsAndroid.RESULTS.GRANTED;
if(!isGrantedStepsPermission) {
// handle
}
// use the `readRecords` API like normal
const stepsRecords = await readRecords('Steps', {/* ... */});
That documentation is very misleading tho, because it doesn't enumerate the health permissions, but it worked for me when I just encoded the permission string myself. <-- this is untrue, it doesn't work if it is not enumerated
To be honest, seeing the built-in native PermissionsAndroid
modules makes me question why this package exposes a requestPermission
function at all, if there is already a way to do this via react-native, seems like suggesting the use of this module would be best and less maintenance for this package. Curious if anyone else was doing this workaround or if they have more context into why this library has a custom requestPermission
over the built-in react-native one
If you want to make any small changes to your packages, use patch-package to patch your modules instead of commiting your node_modules folder.
@matinzd I did @LeonNissen changes in node modules and created patch package after that i am getting issue for Permission Denial: starting Intent { act=android.health.connect.action.REQUEST_HEALTH_PERMISSIONS cmp=com.google.android.healthconnect.controller/com.android.healthconnect.controller.permissions.request.PermissionsActivity } requires android.permission.GRANT_RUNTIME_PERMISSIONS
Please help on this Thanks in advance
I'm also having the same issue that @chganesh does. I don't know what the problem is, I simply tried to run the repo @LeonNissen put up.
EDIT: Works on my other computer. Still would love to know how to fix the problem.
Hi @chganesh and @qtdinh,
I'm sorry I haven't tested the code before committing...
I committed a new version with the intent android.health.connect.action.MANAGE_HEALTH_PERMISSIONS
.
It works now 🚀
Thanks @matinzd for the patch-package
heads up, I will look into that!
Hello @LeonNissen , I edited according to you but I got an error yarn run v1.22.19 $ react-native run-android info Starting JS server... info Installing the app...
Task :react-native-health-connect:compileDebugKotlin FAILED 45 actionable tasks: 2 executed, 43 up-to-date
info 💡 Tip: Make sure that you have set up your development environment correctly, by running react-native doctor. To read more about doctor command visit: https://github.com/react-native-community/cli/blob/main/packages/cli-doctor/README.md#doctor
e: file:///E:/AppHealthConnect/node_modules/react-native-health-connect/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt:85:23 Unresolved reference: Build e: file:///E:/AppHealthConnect/node_modules/react-native-health-connect/android/src/main/java/dev/matinzd/healthconnect/HealthConnectManager.kt:85:48 Unresolved reference: Build
FAILURE: Build failed with an exception.
What went wrong: Execution failed for task ':react-native-health-connect:compileDebugKotlin'.
A failure occurred while executing org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers$GradleKotlinCompilerWorkAction Compilation error. See log for more details
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 5s error Failed to install the app. info Run CLI with --verbose flag for more details. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Hi @sangle-zotek8!
Have you imported Build
? (add import android.os.Build
at the top of HealthConnectManager.kt
)
Hello !
I have had the same issue for some months and since nothing has been done yet, I've looked into it. I have managed to make it work on Android 14 and from what I've seen, it seems that Android 14 doesn't like us using startActivityForResult to ask for permissions and wants registerForActivityResult instead. And on top of this, there's an issue with react-native that prevents registerForActivityResult from calling its callback ! (https://github.com/facebook/react-native/issues/42403)
Here's a project I made where you can find a working example: https://github.com/LimAlbert/react-native-health-connect-android14
The code is far from perfect since I'm not really a native developper but at least it works (I haven't tested everything though)
It seems you are right @LimAlbert. The main issue when I was implementing this library was the RN limitation regarding the new way of handling activity results and permission contracts.
The patch you provided seems ok, but it needs some more work because we are calling setProvider
inside the MainActivity.kt
which is not ideal.
@cortinico Are there any roadmaps/plan to support Androidx Activity Result APIs inside native modules?
I started investigating this. @LimAlbert You are right. There is a problem with RN core. Do you want to send a pull request to fix that?
@matinzd Thanks for your work ! I have made a PR for the onRequestPermissionsResult issue (https://github.com/facebook/react-native/pull/42478)
For all those wondering about this issue, I have some updates:
There is an open PR, as you can see, that can address this problem. Once it gets merged, there will be a breaking change in the library. You will need to modify your MainActivity file to set the permission delegate and set up the proper AndroidManifest for permission rationale on Android 14 and above. See here for more information: https://github.com/matinzd/react-native-health-connect/pull/60
We are currently awaiting meta to backport the permission contract issue to older versions of RN. This implies that after the new release, we will likely only support RN 70 and above, and the latest patch version, as the backport may only be available for recent RN versions. If you want to follow up on this matter, please read here: https://github.com/reactwg/react-native-releases/discussions/98#discussioncomment-8208768. Thanks to @LimAlbert for sending a fix.
@matinzd What is the process for updating your package or adding those changes to my current package and applying a patch? My Current Versions react-native-health-connect": "^1.1.0 react-native": "0.72.4"
@matinzd @LimAlbert Please help on this
@chganesh If you can't upgrade to react-native@0.73.3, follow what I've written regarding react-native here (Edit the source code and then use patch-package to create patch)
For react-native-health-connect, you can use the pr that @matinzd made, it should be working
@AlbertCardi Edited my source code to reflect changes made by @LimAlbert and @matinzd PR. Thanks @matinzd @LimAlbert @AlbertCardi
As of now retrieve last 30 days steps below method follow const last30DaysMetrics: any = [] const last30Days: any = [] // Loop through the last 7 days for (let i = 30; i >= 0; i--) { const currentDate = new Date() currentDate.setDate(currentDate.getDate() - i) // Subtract i days // Get the day name (e.g., "Sunday", "Monday", etc.) const dayName = new Intl.DateTimeFormat('en-US', { weekday: 'long' }).format(currentDate) // Store the health metrics for the current day
const steps = await readRecords('Steps', {
timeRangeFilter: {
operator: 'between',
startTime: new Date(currentDate.setHours(0, 0, 0, 0)).toISOString(),
endTime: new Date(currentDate.setHours(23, 59, 59, 999)).toISOString(),
},
}).then(result => {
const daySteps = result.reduce((sum, cur) => sum + cur.count, 0)
// let frontColor = ''
// if (daySteps > 3000) {
let frontColor = '#177AD5'
// }
last30Days.push({
label: currentDate,
value: daySteps,
frontColor: frontColor,
})
last30DaysMetrics.push({
label: moment.utc(currentDate).local().format('ddd DD'),
value: daySteps,
frontColor: frontColor,
})
})
}
setWeekData(last30DaysMetrics)
setOneMonthSteps(last30Days)
if any better way to get last 30 days please let me know Thanks in advance
@matinzd after upgrading to v2.0.0, it is not asking for permission for health connect datatypes in android 14. my App is not showing in health connect App permissions list
react-native: 0.73.4 react-native-health-connect: 2.0.0
I also tested in android 13 device it is working fine and asking for permissions
Have you checked the latest release for the changes? You need to add some code to your MainActivity.kt.
@matinzd yes I already made the changes in MainActivity.kt
@matinzd is there anything else that I am missing..
Try checking the example app changes and see if you are missing anything:
I may have missed something in the documentation.
I tried running example app but getting this issue https://github.com/matinzd/react-native-health-connect/issues/64 node: v19.8.1
@nHussain18 https://github.com/matinzd/react-native-health-connect/issues/64#issuecomment-1966093049
Use node 18 or there might be something wrong with your environment setup.
Try checking the example app changes and see if you are missing anything:
I may have missed something in the documentation.
@matinzd I checked the example app changes and tried to run it, and it is working fine as aspected.
I notice one change that you have made in example app but not documented. I made these changes in my app, then it is also working fine.
Missed Changes from this PR::
Hi, I encountered the same issue "No Activity found to handle Intent...". After upgrading the plugin to version 2.0.1
, as well as adding the extra changes as @nHussain18, my app no longer crashes when calling requestPermission
. However, now the requestPermission
method never returns on Android 14 when using await
. Does anyone else has this problem?
I tried adding logs in the native code as well, and the following logs are not printed.
fun requestPermission(
reactPermissions: ReadableArray, providerPackageName: String, promise: Promise
) {
Log.d("HealthConnectManager", "before throwUnlessClientIsAvailable")
throwUnlessClientIsAvailable(promise) {
coroutineScope.launch {
val granted = HealthConnectPermissionDelegate.launch(PermissionUtils.parsePermissions(reactPermissions))
Log.d("@requestPermission", "inside coroutine")
promise.resolve(PermissionUtils.mapPermissionResult(granted))
}
}
}
requestPermission = activity.registerForActivityResult(contract) {
coroutineScope.launch {
Log.d("@activityResult", "inside coroutine")
channel.send(it)
coroutineContext.cancel()
}
}
Hi, I encountered the same issue "No Activity found to handle Intent...". After upgrading the plugin to version
2.0.1
, as well as adding the extra changes as @nHussain18, my app no longer crashes when callingrequestPermission
. However, now therequestPermission
method never returns on Android 14 when usingawait
. Does anyone else has this problem?I tried adding logs in the native code as well, and the following logs are not printed.
fun requestPermission( reactPermissions: ReadableArray, providerPackageName: String, promise: Promise ) { Log.d("HealthConnectManager", "before throwUnlessClientIsAvailable") throwUnlessClientIsAvailable(promise) { coroutineScope.launch { val granted = HealthConnectPermissionDelegate.launch(PermissionUtils.parsePermissions(reactPermissions)) Log.d("@requestPermission", "inside coroutine") promise.resolve(PermissionUtils.mapPermissionResult(granted)) } } }
requestPermission = activity.registerForActivityResult(contract) { coroutineScope.launch { Log.d("@activityResult", "inside coroutine") channel.send(it) coroutineContext.cancel() } }
I'm encountering the same issue. Have you found a solution to fix it ?
Hi, I encountered the same issue "No Activity found to handle Intent...". After upgrading the plugin to version
2.0.1
, as well as adding the extra changes as @nHussain18, my app no longer crashes when callingrequestPermission
. However, now therequestPermission
method never returns on Android 14 when usingawait
. Does anyone else has this problem?I tried adding logs in the native code as well, and the following logs are not printed.
fun requestPermission( reactPermissions: ReadableArray, providerPackageName: String, promise: Promise ) { Log.d("HealthConnectManager", "before throwUnlessClientIsAvailable") throwUnlessClientIsAvailable(promise) { coroutineScope.launch { val granted = HealthConnectPermissionDelegate.launch(PermissionUtils.parsePermissions(reactPermissions)) Log.d("@requestPermission", "inside coroutine") promise.resolve(PermissionUtils.mapPermissionResult(granted)) } } }
requestPermission = activity.registerForActivityResult(contract) { coroutineScope.launch { Log.d("@activityResult", "inside coroutine") channel.send(it) coroutineContext.cancel() } }
having same issue. Did you find any solution?
For older versions, I added below code while reading permission
let grantedPermissions = await getGrantedPermissions();
if (grantedPermissions.length === 0) {
// request permissions
grantedPermissions = await requestPermission([
{accessType: 'write', recordType: 'ExerciseSession'},
]);
}
and asked users to manually give permissions via health connect app. Now there is no app crash. requestPermission is triggering the app crash.
Hi, I'm having this issue in lower versions of android, on android 14 is working great but in android 13 and below is crashing due to android.content.ActivityNotFoundException: No Activity found to handle Intent { act=androidx.health.ACTION_REQUEST_PERMISSIONS pkg=com.myapp.app (has extras) }
@matinzd im using react-native cli "react-native": "0.72.3", .... im unable to configure health-connect.. there is some kind of issue
Your manifest is invalid. Please open the Android project in Android Studio for assistance from the IDE to resolve the issue.
Describe the bug Calling
requestPermission
will lead into an error: "No Activity found to handle Intent { act=androidx.activity.result.contract.action.REQUEST_PERMISSIONS (has extras) }However, on Android 13 the issue does not exist.
To Reproduce When trying to request permissions the application crashes with the error (see above)
Expected behavior HealthConnect shows the permission selection (Same behavior as on Android 13).
Screenshots
Environment: