1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-22 19:02:16 +00:00

feat: add back extensions

This commit is contained in:
Florian Bouillon 2023-02-28 00:19:54 +01:00
parent c59481546f
commit 91ba424f9c
Signed by: Florian Bouillon
GPG Key ID: E05B3A94178D3A7C
10 changed files with 87 additions and 118 deletions

View File

@ -231,4 +231,14 @@ dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.10.0") implementation("com.squareup.okhttp3:logging-interceptor:4.10.0")
// Google Fit
implementation("com.google.android.gms:play-services-fitness:21.1.0")
implementation("com.google.android.gms:play-services-auth:20.4.1")
// Google Health Connect
implementation("androidx.health.connect:connect-client:1.0.0-alpha11")
// Samsung Health
implementation(files("libs/samsung-health-data-1.5.0.aar"))
} }

Binary file not shown.

View File

@ -1,78 +0,0 @@
package com.dzeio.openhealth.ui.extensions
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.dzeio.openhealth.adapters.ExtensionAdapter
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.databinding.FragmentExtensionsBinding
import com.dzeio.openhealth.extensions.Extension
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
@AndroidEntryPoint
class ExtensionsFragment :
BaseFragment<ExtensionsViewModel, FragmentExtensionsBinding>(ExtensionsViewModel::class.java) {
companion object {
const val TAG = "ExtensionsFragment"
}
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentExtensionsBinding =
FragmentExtensionsBinding::inflate
private lateinit var activeExtension: Extension
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val recycler = binding.list
val manager = LinearLayoutManager(requireContext())
recycler.layoutManager = manager
val adapter = ExtensionAdapter(viewModel.config)
adapter.onItemClick = {
activeExtension = it
activeExtension.enable(this)
Log.d(TAG, "${it.id}: ${it.name}")
lifecycleScope.launch {
extensionIsConnected(it)
}
}
recycler.adapter = adapter
val list = viewModel.extensions
list.forEach {
it.enable(this)
}
adapter.set(list)
}
private suspend fun extensionIsConnected(it: Extension) {
// check if it is connected
if (it.isConnected()) {
gotoExtension(it)
return
}
val ld = it.connect()
if (ld) {
gotoExtension(it)
}
// handle if extension can't be connected
}
private fun gotoExtension(it: Extension) {
findNavController().navigate(
ExtensionsFragmentDirections.actionNavExtensionsToNavExtension(it.id)
)
}
}

View File

@ -1,16 +0,0 @@
package com.dzeio.openhealth.ui.extensions
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.extensions.ExtensionFactory
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class ExtensionsViewModel @Inject internal constructor(
val config: Configuration
) : BaseViewModel() {
val extensions = ExtensionFactory.getAll()
}

View File

@ -15,10 +15,10 @@ import androidx.health.connect.client.request.ReadRecordsRequest
import androidx.health.connect.client.time.TimeRangeFilter import androidx.health.connect.client.time.TimeRangeFilter
import com.dzeio.openhealth.core.Observable import com.dzeio.openhealth.core.Observable
import com.dzeio.openhealth.data.weight.Weight import com.dzeio.openhealth.data.weight.Weight
import java.time.Instant
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.time.Instant
@RequiresApi(Build.VERSION_CODES.P) @RequiresApi(Build.VERSION_CODES.P)
class HealthConnectExtension : Extension { class HealthConnectExtension : Extension {
@ -29,13 +29,12 @@ class HealthConnectExtension : Extension {
// build a set of permissions for required data types // build a set of permissions for required data types
val PERMISSIONS = val PERMISSIONS =
setOf( setOf(
HealthPermission.createReadPermission(HeartRateRecord::class), HealthPermission.getReadPermission(HeartRateRecord::class),
HealthPermission.createWritePermission(HeartRateRecord::class), HealthPermission.getWritePermission(HeartRateRecord::class),
HealthPermission.createReadPermission(StepsRecord::class), HealthPermission.getReadPermission(StepsRecord::class),
HealthPermission.createWritePermission(StepsRecord::class) HealthPermission.getWritePermission(StepsRecord::class)
) )
override val id = "HealthConnect" override val id = "HealthConnect"
override val name = "Health Connect" override val name = "Health Connect"
@ -51,15 +50,13 @@ class HealthConnectExtension : Extension {
override suspend fun isConnected(): Boolean = true override suspend fun isConnected(): Boolean = true
private val connectionStatus = Observable(false) private val connectionStatus = Observable(false)
private lateinit var fragment: Fragment private lateinit var fragment: Fragment
private lateinit var client: HealthConnectClient private lateinit var client: HealthConnectClient
override fun isAvailable(): Boolean { override fun isAvailable(): Boolean {
return HealthConnectClient.isAvailable(fragment.requireContext()) return HealthConnectClient.isProviderAvailable(fragment.requireContext())
} }
override fun enable(fragment: Fragment): Boolean { override fun enable(fragment: Fragment): Boolean {
@ -116,7 +113,6 @@ class HealthConnectExtension : Extension {
) )
) )
} }
} }
override suspend fun exportWeights(weight: Array<Weight>): Flow<Extension.TaskProgress<Unit>> { override suspend fun exportWeights(weight: Array<Weight>): Flow<Extension.TaskProgress<Unit>> {
@ -128,10 +124,10 @@ class HealthConnectExtension : Extension {
// signIn(Data.values()[requestCode]) // signIn(Data.values()[requestCode])
} }
override val contract: ActivityResultContract<Set<HealthPermission>, Set<HealthPermission>> override val contract: ActivityResultContract<Set<String>, Set<String>>
get() = PermissionController.createRequestPermissionResultContract() get() = PermissionController.createRequestPermissionResultContract()
override suspend fun permissionsGranted(): Boolean { override suspend fun permissionsGranted(): Boolean {
return this.client.permissionController.getGrantedPermissions(this.PERMISSIONS).containsAll(this.PERMISSIONS) return this.client.permissionController.getGrantedPermissions().containsAll(this.PERMISSIONS)
} }
} }

View File

@ -38,7 +38,7 @@ class ExtensionFragment :
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
if (this.extension.contract != null) { if (this.extension.contract != null) {
this.request = this.request =
registerForActivityResult<Any, Any>(this.extension.contract!! as ActivityResultContract<Any, Any>) { registerForActivityResult(this.extension.contract!! as ActivityResultContract<Any, Any>) {
this.extension.onActivityResult(it as Any) this.extension.onActivityResult(it as Any)
} }
} }

View File

@ -8,6 +8,7 @@ import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.dzeio.openhealth.adapters.ItemAdapter
import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.databinding.FragmentExtensionsBinding import com.dzeio.openhealth.databinding.FragmentExtensionsBinding
import com.dzeio.openhealth.extensions.Extension import com.dzeio.openhealth.extensions.Extension
@ -35,21 +36,23 @@ class ExtensionsFragment :
val manager = LinearLayoutManager(requireContext()) val manager = LinearLayoutManager(requireContext())
recycler.layoutManager = manager recycler.layoutManager = manager
val adapter = ExtensionAdapter(viewModel.config) val adapter = ItemAdapter<Extension>()
adapter.onItemClick = { adapter.onItemClick = {
activeExtension = it activeExtension = it.value
activeExtension.enable(this) activeExtension.enable(this)
Log.d(TAG, "${it.id}: ${it.name}") Log.d(TAG, "${activeExtension.id}: ${activeExtension.name}")
lifecycleScope.launch { lifecycleScope.launch {
extensionIsConnected(it) extensionIsConnected(activeExtension)
} }
} }
recycler.adapter = adapter recycler.adapter = adapter
val list = viewModel.extensions val list = viewModel.extensions.map {
list.forEach { ItemAdapter.Item(
it.enable(this) it,
it.name
)
} }
adapter.set(list) adapter.set(list)
@ -71,7 +74,7 @@ class ExtensionsFragment :
private fun gotoExtension(it: Extension) { private fun gotoExtension(it: Extension) {
findNavController().navigate( findNavController().navigate(
ExtensionsFragmentDirections.actionNavExtensionsToNavExtension(it.id) ExtensionsFragmentDirections.actionExtensionsFragmentToExtensionFragment(it.id)
) )
} }
} }

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_margin="16dp"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="@+id/import_button"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:text="Force Import" />
<Button
android:id="@+id/export_button"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:text="Force Export" />
</LinearLayout>
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/extension_informations" />
</LinearLayout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list"
tools:listitem="@layout/item_list"
tools:context=".ui.extensions.ExtensionsFragment" />

View File

@ -223,5 +223,11 @@
<fragment <fragment
android:id="@+id/extensionFragment" android:id="@+id/extensionFragment"
android:name="com.dzeio.openhealth.ui.extension.ExtensionFragment" android:name="com.dzeio.openhealth.ui.extension.ExtensionFragment"
android:label="ExtensionFragment" /> android:label="ExtensionFragment">
<argument
android:name="extension"
app:argType="string"
/>
</fragment>
</navigation> </navigation>