Native
Android library for integrating WeFitter and Health Connect into your app
Installation
Add wefitter-health-connect-0.1.2.aar
to libs
folder which should normally be in app/libs
.
Add the following dependencies to your app/build.gradle
:
Hide code example
dependencies {
implementation fileTree(dir: 'libs', include: ['*.aar'])
implementation 'androidx.health.connect:connect-client:1.1.0-alpha07'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.3'
implementation 'androidx.security:security-crypto:1.0.0'
implementation 'androidx.work:work-runtime-ktx:2.9.0'
implementation 'com.auth0.android:jwtdecode:2.0.2'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
implementation 'androidx.activity:activity-compose:1.9.0'
}
Usage
Add the following to your MainActivity.kt
:
Breaking change: you MUST have requested and granted the android.Manifest.permission.ACTIVITY_RECOGNITION permission in order to connect the WeFitter SDK. If not granted, the connection to WeFitter SDK will fail.
Furthermore, you can configure the list of App permissions your App has been approved for, so that the user only gets to see those permissions to grante access to his health data.
Hide code example
import com.wefitter.healthconnect.WeFitterHealthConnect
import com.wefitter.healthconnect.WeFitterHealthConnectError
class MainActivity : AppCompatActivity() {
private val prefix = "android.permission.health"
private val app_permissions = setOf(
"$prefix.READ_DISTANCE",
"$prefix.READ_STEPS",
"$prefix.READ_TOTAL_CALORIES_BURNED",
"$prefix.READ_HEART_RATE",
"$prefix.READ_POWER",
"$prefix.READ_EXERCISE",
//"$prefix.READ_BLOOD_GLUCOSE",
//"$prefix.READ_BLOOD_PRESSURE",
//"$prefix.READ_BODY_FAT",
//"$prefix.READ_BODY_TEMPERATURE",
"$prefix.READ_HEIGHT",
//"$prefix.READ_OXYGEN_SATURATION",
"$prefix.READ_WEIGHT",
"$prefix.READ_SPEED",
"$prefix.READ_SLEEP",
)
private val healthConnectPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
Log.i(TAG, "permissions $permissions")
when {
permissions.getOrDefault(android.Manifest.permission.ACTIVITY_RECOGNITION, false) -> {
}
permissions.getOrDefault(android.Manifest.permission.POST_NOTIFICATIONS, false) -> {
}
else -> {
// No health connect access granted, service can't be started as it will crash
Toast.makeText(this, "Health permission is required!", Toast.LENGTH_SHORT).show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// initialize WeFitter for Health Connect
val client = WeFitterHealthConnect(this)
healthConnectPermissionRequest.launch(
arrayOf(
android.Manifest.permission.ACTIVITY_RECOGNITION,
android.Manifest.permission.POST_NOTIFICATIONS))
// enter the token from the `bearer` field you receive in the response when a WeFitter profile was created via the [WeFitter API](https://www.wefitter.com/en-us/developers/documentation/#operation/profile_create)
val token = "BEARER_TOKEN"
// initil
setContent {
var checkedState by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf("") }
// create statusListener to receive status changes and errors
val statusListener = object : WeFitterHealthConnect.StatusListener {
override fun onConfigured(configured: Boolean) {
Log.i(WeFitterHealthConnect.TAG, "configured: $configured")
}
override fun onConnected(connected: Boolean) {
Log.i(WeFitterHealthConnect.TAG, "connected: $connected")
checkedState = connected
}
override fun onError(error: WeFitterHealthConnectError) {
Log.e(WeFitterHealthConnect.TAG, "error: ${error.message}")
errorMessage = error.message
}
}
// `configure` should be called every time your app opens
client.configure(
token = token,
statusListener = statusListener,
appPermissions = app_permissions
)
WeFitterForHealthConnectTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background,
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Switch(checked = checkedState, onCheckedChange = {
if (it) {
client.connect()
} else {
client.disconnect()
}
})
Text(
text = errorMessage, color = Color.Red
)
}
}
}
}
}
}