Menu

 

Native

Android library for integrating WeFitter and Samsung Health into your app. If you want this native SDK, please contact WeFitter at support@wefitter.com. The React Native bridge is available on the public github pages.

Installation

Add wefitter-shealth-2.1.1.aar and samsung-health-data-1.5.0.aar to libs folder which should normally be in app/libs.

 

Add the following dependencies to your app/build.gradle:

Show code example
Hide code example
dependencies {
    implementation 'androidx.core:core-ktx:1.13.1'
    implementation 'androidx.appcompat:appcompat:1.7.0'
    implementation 'com.google.android.material:material:1.11.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.compose.material3:material3-android:1.2.1'
    testImplementation 'junit:junit:4.13.2'
    implementation 'androidx.work:work-runtime-ktx:2.9.0'
    implementation 'androidx.lifecycle:lifecycle-service:2.8.3'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    implementation 'androidx.activity:activity-compose:1.9.0'
    implementation platform('androidx.compose:compose-bom:2024.06.00')

    implementation files('libs/samsung-health-data-1.5.0.aar')
    implementation project(path: ':wefitter-shealth')
}

 

Usage

Add the following to your MainActivity.kt:

Breaking changes!!! Make sure you request android.Manifest.permission.ACTIVITY_RECOGNITION before you configure the WeFitter SDK, as without this permission the SDK will never connect!

 

Show code example
Hide code example

import com.wefitter.shealth.WeFitterSHealth
import com.wefitter.shealth.WeFitterSHealthError

class MainActivity : AppCompatActivity() {

    private lateinit var weFitterSHealth: WeFitterSHealth
    private var isConfigured: Boolean = false

    private var ACTIVITY_RECOGNITION: Boolean = false
    private var POST_NOTIFICATIONS: Boolean = false

    private val prefix = "com.samsung.health"

    // Change the below set of app permissions to reflect your app's approved permissions by Samsung
    // Only the below permissions will be asked to the user for approval
    private val app_permissions = setOf(
        "com.samsung.shealth.step_daily_trend",
        "$prefix.heart_rate",
        "$prefix.height",
        "$prefix.weight",
        "$prefix.sleep_stage",
        "$prefix.exercise",
        //"$prefix.blood_glucose",
        //"$prefix.blood_pressure",
        //"$prefix.body_fat",
        //"$prefix.body_temperature",
        //"$prefix.oxygen_saturation",
    )


    private val healthConnectPermissionRequest = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        Log.i(TAG, "permissions $permissions")
        when {
            permissions.getOrDefault(android.Manifest.permission.ACTIVITY_RECOGNITION, false) -> {
                ACTIVITY_RECOGNITION = true
                if (isConfigured && !weFitterSHealth.isConnected()) {
                    weFitterSHealth.connect()
                }
            }

            permissions.getOrDefault(android.Manifest.permission.POST_NOTIFICATIONS, false) -> {
                POST_NOTIFICATIONS = true

            }
            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)

        setContentView(R.layout.activity_main)

        healthConnectPermissionRequest.launch(
            arrayOf(
                android.Manifest.permission.ACTIVITY_RECOGNITION,
                android.Manifest.permission.POST_NOTIFICATIONS))


        // create instance of WeFitterSHealth
        weFitterSHealth = WeFitterSHealth(this)

        // create statusListener to receive status changes and errors - optional
        val statusListener = object : WeFitterSHealth.StatusListener {
            override fun onConfigured(configured: Boolean) {
                Log.i(WeFitterSHealth.TAG, "configured: $configured")

                // enable connection if it hasn't already been enabled,
                // or move this for example to a button press or toggle change
                // and then `weFitterSHealth.disconnect()` is also useful.
                isConfigured = true
                // if (configured && !weFitterSHealth.isConnected()) {
                //     weFitterSHealth.connect()
                // }
            }

            override fun onConnected(connected: Boolean) {
                Log.i(WeFitterSHealth.TAG, "connected: $connected")
            }

            override fun onError(error: WeFitterSHealthError) {
                Log.e(WeFitterSHealth.TAG, "error: ${error.reason.message}")

                // `resolvable` boolean indicates the error can be passed to `tryToResolveError` function
                // `reason` can be checked to override specific messages
                if (error.reason.resolvable) {
                    AlertDialog.Builder(this@MainActivity)
                        .setMessage(error.reason.message)
                        .setPositiveButton(android.R.string.ok) { _, _ ->
                            // `tryToResolveError` will guide the user on fixing certain errors
                            // for example:
                            // - link to the app store to install or update Samsung Health
                            // - open Samsung Health to accept privacy policy
                            // - open Settings when Samsung Health needs to be enabled
                            weFitterSHealth.tryToResolveError(error)
                        }
                        .setNegativeButton(android.R.string.cancel, null)
                        .show()
                }
            }
        }

        // customize notification - optional
        val notificationConfig = WeFitterSHealth.NotificationConfig().apply {
            // override fields
            title = "CUSTOM_TITLE"
            text = "CUSTOM_TEXT"
            iconResourceId = R.mipmap.ic_notification // pass custom icon resource id
            channelId = "CUSTOM_CHANNEL_ID"
            channelName = "CUSTOM_CHANNEL_NAME"
        }

        // configure WeFitterSHealth
        // token should be jwt and contain an id corresponding to a WeFitter profile
        // api url should be base without v1.3/ingest/ as the library will append this
        // for example: https://api.wefitter.com/api/
        weFitterSHealth.configure("YOUR_TOKEN", "YOUR_API_URL", statusListener, notificationConfig, appPermissions = app_permissions)
    }


    companion object {
        const val TAG = "MainActivity"
    }

}

Thank you for reaching out!

We will be in touch with you soon. WeFitter team.

You are subscribed!

You will soon receive our newsletter!
WeFitter team.