+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ */
+package com.dzeio.openhealth.devices.libs;
+
+
+
+
+/**
+ * based on ... by prototux
+ *
+ * TODO: Carefully transform it into a Kotlin Class
+ */
+public class MiScaleLib {
+ private final int sex; // male = 1; female = 0
+ private final int age;
+ private final float height;
+
+ public MiScaleLib(int sex, int age, float height) {
+ this.sex = sex;
+ this.age = age;
+ this.height = height;
+ }
+
+ private float getLBMCoefficient(float weight, float impedance) {
+ float lbm = (height * 9.058f / 100.0f) * (height / 100.0f);
+ lbm += weight * 0.32f + 12.226f;
+ lbm -= impedance * 0.0068f;
+ lbm -= age * 0.0542f;
+
+ return lbm;
+ }
+
+ public float getBMI(float weight) {
+ return weight / (((height * height) / 100.0f) / 100.0f);
+ }
+
+ public float getLBM(float weight, float impedance) {
+ float leanBodyMass = weight - ((getBodyFat(weight, impedance) * 0.01f) * weight) - getBoneMass(weight, impedance);
+
+ if (sex == 0 && leanBodyMass >= 84.0f) {
+ leanBodyMass = 120.0f;
+ }
+ else if (sex == 1 && leanBodyMass >= 93.5f) {
+ leanBodyMass = 120.0f;
+ }
+
+ return leanBodyMass;
+ }
+
+ public float getMuscle(float weight, float impedance) {
+ return this.getLBM(weight,impedance); // this is wrong but coherent with MiFit app behaviour
+ }
+
+ public float getWater(float weight, float impedance) {
+ float coeff;
+ float water = (100.0f - getBodyFat(weight, impedance)) * 0.7f;
+
+ if (water < 50) {
+ coeff = 1.02f;
+ } else {
+ coeff = 0.98f;
+ }
+
+ return coeff * water;
+ }
+
+ public float getBoneMass(float weight, float impedance) {
+ float boneMass;
+ float base;
+
+ if (sex == 0) {
+ base = 0.245691014f;
+ }
+ else {
+ base = 0.18016894f;
+ }
+
+ boneMass = (base - (getLBMCoefficient(weight, impedance) * 0.05158f)) * -1.0f;
+
+ if (boneMass > 2.2f) {
+ boneMass += 0.1f;
+ }
+ else {
+ boneMass -= 0.1f;
+ }
+
+ if (sex == 0 && boneMass > 5.1f) {
+ boneMass = 8.0f;
+ }
+ else if (sex == 1 && boneMass > 5.2f) {
+ boneMass = 8.0f;
+ }
+
+ return boneMass;
+ }
+
+ public float getVisceralFat(float weight) {
+ float visceralFat = 0.0f;
+ if (sex == 0) {
+ if (weight > (13.0f - (height * 0.5f)) * -1.0f) {
+ float subsubcalc = ((height * 1.45f) + (height * 0.1158f) * height) - 120.0f;
+ float subcalc = weight * 500.0f / subsubcalc;
+ visceralFat = (subcalc - 6.0f) + (age * 0.07f);
+ }
+ else {
+ float subcalc = 0.691f + (height * -0.0024f) + (height * -0.0024f);
+ visceralFat = (((height * 0.027f) - (subcalc * weight)) * -1.0f) + (age * 0.07f) - age;
+ }
+ }
+ else {
+ if (height < weight * 1.6f) {
+ float subcalc = ((height * 0.4f) - (height * (height * 0.0826f))) * -1.0f;
+ visceralFat = ((weight * 305.0f) / (subcalc + 48.0f)) - 2.9f + (age * 0.15f);
+ }
+ else {
+ float subcalc = 0.765f + height * -0.0015f;
+ visceralFat = (((height * 0.143f) - (weight * subcalc)) * -1.0f) + (age * 0.15f) - 5.0f;
+ }
+ }
+
+ return visceralFat;
+ }
+
+ public float getBodyFat(float weight, float impedance) {
+ float bodyFat = 0.0f;
+ float lbmSub = 0.8f;
+
+ if (sex == 0 && age <= 49) {
+ lbmSub = 9.25f;
+ } else if (sex == 0) {
+ lbmSub = 7.25f;
+ }
+
+ float lbmCoeff = getLBMCoefficient(weight, impedance);
+ float coeff = 1.0f;
+
+ if (sex == 1 && weight < 61.0f) {
+ coeff = 0.98f;
+ }
+ else if (sex == 0 && weight > 60.0f) {
+ coeff = 0.96f;
+
+ if (height > 160.0f) {
+ coeff *= 1.03f;
+ }
+ } else if (sex == 0 && weight < 50.0f) {
+ coeff = 1.02f;
+
+ if (height > 160.0f) {
+ coeff *= 1.03f;
+ }
+ }
+
+ bodyFat = (1.0f - (((lbmCoeff - lbmSub) * coeff) / weight)) * 100.0f;
+
+ if (bodyFat > 63.0f) {
+ bodyFat = 75.0f;
+ }
+
+ return bodyFat;
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt b/app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt
index 5a5e697..79f4983 100644
--- a/app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt
+++ b/app/src/main/java/com/dzeio/openhealth/di/SystemModule.kt
@@ -3,6 +3,7 @@ package com.dzeio.openhealth.di
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
+import com.dzeio.openhealth.utils.Bluetooth
import com.dzeio.openhealth.utils.Configuration
import dagger.Module
import dagger.Provides
@@ -29,4 +30,8 @@ class SystemModule {
fun provideConfig(sharedPreferences: SharedPreferences): Configuration {
return Configuration(sharedPreferences)
}
+
+ @Singleton
+ @Provides
+ fun provideBluetooth(@ApplicationContext context: Context): Bluetooth = Bluetooth(context)
}
diff --git a/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt b/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt
index 6f5b765..e40226f 100644
--- a/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt
+++ b/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt
@@ -20,6 +20,8 @@ import com.dzeio.openhealth.data.step.StepRepository_Factory
import com.dzeio.openhealth.data.step.StepSource
import com.dzeio.openhealth.interfaces.NotificationChannels
import com.dzeio.openhealth.interfaces.NotificationIds
+import com.dzeio.openhealth.utils.polyfills.NotificationBehavior
+import com.dzeio.openhealth.utils.polyfills.stopForegroundPoly
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
@@ -101,7 +103,7 @@ class OpenHealthService : Service() {
if (step != null) {
step.value += stepsBuffer
stepRepository.updateStep(step)
- // create a new steps object and send it
+ // create a new steps object and send it
} else {
stepRepository.addStep(Step(value = stepsBuffer))
}
@@ -119,7 +121,7 @@ class OpenHealthService : Service() {
}
override fun onDestroy() {
- stopForeground(true)
+ stopForegroundPoly(NotificationBehavior.REMOVE)
// Tell the user we stopped.
Toast.makeText(this, "Service stopped", Toast.LENGTH_SHORT).show()
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt
index 83e6a6d..98d3b42 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt
@@ -116,7 +116,6 @@ class BrowseFragment :
)
)
}
-
}
private fun updateStepsText(numberOfSteps: Int?, goal: Int?) {
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseViewModel.kt
index 6ab13ab..5335aae 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseViewModel.kt
@@ -9,15 +9,15 @@ import com.dzeio.openhealth.data.step.StepRepository
import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class BrowseViewModel @Inject internal constructor(
stepRepository: StepRepository,
weightRepository: WeightRepository,
- private val config: Configuration
+ config: Configuration
) : BaseViewModel() {
private val _steps = MutableLiveData(0)
@@ -41,6 +41,5 @@ class BrowseViewModel @Inject internal constructor(
_weight.postValue(it.weight)
}
}
-
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialog.kt
index a4fec23..4f33981 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialog.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialog.kt
@@ -22,7 +22,6 @@ class FoodDialog :
private var quantity: Float? = null
-
override val bindingInflater: (LayoutInflater) -> DialogFoodProductBinding =
DialogFoodProductBinding::inflate
@@ -50,7 +49,6 @@ class FoodDialog :
}
}
-
override fun onCreated() {
super.onCreated()
Log.d("FoodDialog", args.id.toString())
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialogViewModel.kt
index 07fa6a2..59b9f27 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialogViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodDialogViewModel.kt
@@ -6,9 +6,9 @@ import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.food.Food
import com.dzeio.openhealth.data.food.FoodRepository
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class FoodDialogViewModel @Inject internal constructor(
@@ -41,7 +41,7 @@ class FoodDialogViewModel @Inject internal constructor(
return
}
- val transformer = (quantity ?: it.quantity) / it.quantity
+ val transformer = quantity / it.quantity
it.energy = it.energy * transformer
it.proteins = it.proteins * transformer
it.carbohydrates = it.carbohydrates * transformer
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeFragment.kt
index a9f2b9e..38110c1 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeFragment.kt
@@ -64,7 +64,6 @@ class FoodHomeFragment :
proteins += food.proteins / 100 * food.quantity
carbohydrates += food.carbohydrates / 100 * food.quantity
fat += food.fat / 100 * food.quantity
-
}
binding.energyTxt.text = "${energy.toInt()} / 2594kcal"
binding.energyBar.progress = (100 * energy / 2594).toInt()
@@ -87,7 +86,9 @@ class FoodHomeFragment :
viewModel.date.observe(viewLifecycleOwner) {
val date = Calendar.getInstance()
date.timeInMillis = it
- binding.date.text = "${date.get(Calendar.YEAR)}-${date.get(Calendar.MONTH) + 1}-${date.get(Calendar.DAY_OF_MONTH)}"
+ binding.date.text = "${date.get(Calendar.YEAR)}-${date.get(Calendar.MONTH) + 1}-${date.get(
+ Calendar.DAY_OF_MONTH
+ )}"
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeViewModel.kt
index 3bc5b93..a47fee9 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/food/FoodHomeViewModel.kt
@@ -5,17 +5,15 @@ import androidx.lifecycle.viewModelScope
import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.food.Food
import com.dzeio.openhealth.data.food.FoodRepository
-import com.dzeio.openhealth.data.openfoodfact.OpenFoodFactService
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
import java.util.Calendar
import javax.inject.Inject
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
@HiltViewModel
class FoodHomeViewModel @Inject internal constructor(
- private val foodRepository: FoodRepository,
- private val foodFactService: OpenFoodFactService
+ private val foodRepository: FoodRepository
) : BaseViewModel() {
val items: MutableLiveData> = MutableLiveData()
private val list: MutableLiveData> = MutableLiveData(arrayListOf())
@@ -62,8 +60,10 @@ class FoodHomeViewModel @Inject internal constructor(
day.add(Calendar.DAY_OF_YEAR, 1)
val tomorrow = day.timeInMillis
- items.postValue((foods ?: list.value!!).filter { food ->
- food.timestamp in todayInMillis until tomorrow
- })
+ items.postValue(
+ (foods ?: list.value!!).filter { food ->
+ food.timestamp in todayInMillis until tomorrow
+ }
+ )
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt
index 430d0af..74f098c 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/food/SearchFoodDialogViewModel.kt
@@ -7,9 +7,9 @@ import com.dzeio.openhealth.data.food.Food
import com.dzeio.openhealth.data.food.FoodRepository
import com.dzeio.openhealth.utils.NetworkResult
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class SearchFoodDialogViewModel @Inject internal constructor(
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt
index dee8064..5b378a5 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt
@@ -7,12 +7,14 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.view.LayoutInflater
+import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.dzeio.charts.Entry
import com.dzeio.charts.axis.Line
import com.dzeio.charts.series.LineSerie
+import com.dzeio.openhealth.BuildConfig
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
@@ -98,6 +100,17 @@ class HomeFragment : BaseFragment(HomeViewMo
series = arrayListOf(serie)
}
+ if (BuildConfig.DEBUG) {
+ binding.gotoTests.apply {
+ visibility = View.VISIBLE
+ setOnClickListener {
+ findNavController().navigate(
+ HomeFragmentDirections.actionNavHomeToTestsFragment()
+ )
+ }
+ }
+ }
+
// Update the water intake Graph when the water intake changes
viewModel.water.observe(viewLifecycleOwner) {
if (it != null) {
@@ -218,7 +231,7 @@ class HomeFragment : BaseFragment(HomeViewMo
animator.duration = 300 // ms
animator.addUpdateListener {
this.oldValue = (it.animatedValue as Int).toFloat()
- val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake.toFloat()
+ val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake
val graph = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(graph)
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt
index dcab8ca..dfc5928 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeViewModel.kt
@@ -13,9 +13,9 @@ import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject internal constructor(
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt
index fe8a7dc..640e794 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt
@@ -40,7 +40,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
// Force only numbers on Goal
val weightGoal = findPreference("tmp_goal_weight")
weightGoal?.apply {
-
setOnBindEditTextListener {
it.setSelectAllOnFocus(true)
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
@@ -60,7 +59,6 @@ class SettingsFragment : PreferenceFragmentCompat() {
return@setOnPreferenceClickListener true
}
-
setOnPreferenceChangeListener { _, newValue ->
val unit = config.getString(Settings.MASS_UNIT).value
var modifier = Units.Mass.KILOGRAM.modifier
@@ -91,10 +89,5 @@ class SettingsFragment : PreferenceFragmentCompat() {
return@setOnPreferenceChangeListener true
}
-
- val stepsGoalPreference = findPreference(Settings.STEPS_GOAL)
- stepsGoalPreference.apply {
-
- }
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt
index ba227d7..05a7b77 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt
@@ -129,8 +129,12 @@ class StepsHomeFragment :
return@observe
}
- val filtered = if (!isDay) list else list.filter {
- it.getDay() == args.day
+ val filtered = if (!isDay) {
+ list
+ } else {
+ list.filter {
+ it.getDay() == args.day
+ }
}
if (isDay) {
adapter.set(filtered)
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeViewModel.kt
index cec1ed5..4e4e189 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeViewModel.kt
@@ -9,9 +9,9 @@ import com.dzeio.openhealth.data.step.Step
import com.dzeio.openhealth.data.step.StepRepository
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class StepsHomeViewModel@Inject internal constructor(
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsFragment.kt
new file mode 100644
index 0000000..e838924
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsFragment.kt
@@ -0,0 +1,46 @@
+package com.dzeio.openhealth.ui.tests
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.dzeio.openhealth.core.BaseFragment
+import com.dzeio.openhealth.databinding.FragmentTestsBinding
+import com.dzeio.openhealth.utils.Bluetooth
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class TestsFragment :
+ BaseFragment(TestsViewModel::class.java) {
+
+ override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentTestsBinding
+ get() = FragmentTestsBinding::inflate
+
+ @SuppressLint("MissingPermission")
+ override fun onStart() {
+ super.onStart()
+
+ // Bindings
+ binding.button.setOnClickListener {
+ Bluetooth(requireContext()).apply {
+// scanDevices(cb)
+
+// val device = DeviceMiSmartScale2(requireContext())
+//
+// device.status.addObserver {
+// Log.d("Device", "New device status $it")
+//
+// if (it == Device.ConnectionStatus.CONNECTED) {
+// device.fetchWeights().addObserver {
+// Log.i(
+// "FetchStatus",
+// "${(it.progress.toFloat() / it.progressMax.toFloat() * 100f).roundToInt()}% ${it.progress}/${it.progressMax}"
+// )
+// }
+// }
+// }
+//
+// device.connect()
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsViewModel.kt
new file mode 100644
index 0000000..1cbcdfa
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/ui/tests/TestsViewModel.kt
@@ -0,0 +1,8 @@
+package com.dzeio.openhealth.ui.tests
+
+import com.dzeio.openhealth.core.BaseViewModel
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+@HiltViewModel
+class TestsViewModel @Inject internal constructor() : BaseViewModel()
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterDialog.kt
index 1915680..0ba0697 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterDialog.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterDialog.kt
@@ -48,8 +48,11 @@ class EditWaterDialog :
}
binding.editTextNumber.doOnTextChanged { text, start, before, count ->
val value = text.toString()
- newValue = if (value == "") 0
- else text.toString().toInt()
+ newValue = if (value == "") {
+ 0
+ } else {
+ text.toString().toInt()
+ }
}
binding.date.setOnClickListener {
@@ -100,6 +103,7 @@ class EditWaterDialog :
findNavController().popBackStack()
}
+ @Deprecated("Deprecated in Java")
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_fullscreen_dialog_save -> {
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterViewModel.kt
index 06630ba..e31f1cb 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/water/EditWaterViewModel.kt
@@ -6,9 +6,9 @@ import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.water.WaterRepository
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class EditWaterViewModel @Inject internal constructor(
@@ -36,4 +36,4 @@ class EditWaterViewModel @Inject internal constructor(
waterRepository.addWater(water)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt
index 8552e40..5a06b4f 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterHomeViewModel.kt
@@ -6,9 +6,9 @@ import com.dzeio.openhealth.core.BaseViewModel
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.water.WaterRepository
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class WaterHomeViewModel@Inject internal constructor(
@@ -23,4 +23,4 @@ class WaterHomeViewModel@Inject internal constructor(
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt
index ca4c865..b49f762 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/water/WaterSizeSelectorDialog.kt
@@ -1,7 +1,6 @@
package com.dzeio.openhealth.ui.water
import android.view.LayoutInflater
-import androidx.core.view.marginBottom
import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseDialog
import com.dzeio.openhealth.databinding.DialogWaterSizeSelectorBinding
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialog.kt
index 1d3eec6..0d65fed 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialog.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialog.kt
@@ -23,7 +23,9 @@ import java.util.Date
@AndroidEntryPoint
class EditWeightDialog :
- BaseFullscreenDialog(EditWeightDialogViewModel::class.java) {
+ BaseFullscreenDialog(
+ EditWeightDialogViewModel::class.java
+ ) {
override val bindingInflater: (LayoutInflater) -> DialogEditWeightBinding =
DialogEditWeightBinding::inflate
@@ -97,10 +99,7 @@ class EditWeightDialog :
} else {
TODO("VERSION.SDK_INT < N")
}
-
-
}
-
}
private fun save() {
@@ -140,6 +139,5 @@ class EditWeightDialog :
}
else -> super.onOptionsItemSelected(item)
}
-
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt
index b2f1ac2..e1115c6 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/EditWeightDialogViewModel.kt
@@ -11,9 +11,9 @@ import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class EditWeightDialogViewModel @Inject internal constructor(
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt
index 0795092..dbeeed9 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightFragment.kt
@@ -1,5 +1,6 @@
package com.dzeio.openhealth.ui.weight
+import android.Manifest
import android.content.SharedPreferences
import android.graphics.Paint
import android.os.Bundle
@@ -9,6 +10,8 @@ import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.MenuProvider
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
@@ -16,11 +19,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.dzeio.charts.Entry
import com.dzeio.charts.axis.Line
import com.dzeio.charts.series.LineSerie
+import com.dzeio.openhealth.BuildConfig
import com.dzeio.openhealth.R
import com.dzeio.openhealth.adapters.WeightAdapter
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.databinding.FragmentListWeightBinding
+import com.dzeio.openhealth.utils.PermissionsManager
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import java.text.DateFormat
@@ -34,6 +39,40 @@ class ListWeightFragment :
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) ->
FragmentListWeightBinding = FragmentListWeightBinding::inflate
+ private lateinit var button: View
+ private val activityResult = registerForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) {
+ if (it.containsValue(false)) {
+ // TODO: Show a popup with choice to change it
+ Toast.makeText(requireContext(), R.string.permission_declined, Toast.LENGTH_LONG).show()
+ return@registerForActivityResult
+ }
+
+ button.callOnClick()
+ }
+
+ private val menuProvider = object : MenuProvider {
+ override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
+ menu.findItem(R.id.action_add).isVisible = true
+ }
+
+ override fun onMenuItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.action_add -> {
+ findNavController().navigate(
+ ListWeightFragmentDirections.actionNavListWeightToNavWeightDialog(
+ WeightDialog.DialogTypes.ADD_WEIGHT.ordinal
+ )
+ )
+ true
+ }
+
+ else -> false
+ }
+ }
+ }
+
val settings: SharedPreferences by lazy {
PreferenceManager.getDefaultSharedPreferences(requireContext())
}
@@ -42,26 +81,7 @@ class ListWeightFragment :
super.onViewCreated(view, savedInstanceState)
// Menu
- requireActivity().addMenuProvider(object : MenuProvider {
- override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
- menu.findItem(R.id.action_add).isVisible = true
- }
-
- override fun onMenuItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- R.id.action_add -> {
- findNavController().navigate(
- ListWeightFragmentDirections.actionNavListWeightToNavWeightDialog(
- WeightDialog.DialogTypes.ADD_WEIGHT.ordinal
- )
- )
- true
- }
-
- else -> true
- }
- }
- })
+ requireActivity().addMenuProvider(menuProvider)
if (viewModel.goalWeight.value != null) {
binding.goalButton.setText(R.string.edit_goal)
@@ -75,6 +95,24 @@ class ListWeightFragment :
)
}
+ binding.bluetoothButton.setOnClickListener {
+ val permissions = arrayOf(
+ Manifest.permission.BLUETOOTH,
+ Manifest.permission.BLUETOOTH_CONNECT,
+ Manifest.permission.BLUETOOTH_SCAN,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ )
+ val hasPermission = PermissionsManager.hasPermission(requireContext(), permissions)
+ if (!hasPermission) {
+ button = binding.bluetoothButton
+ activityResult.launch(permissions)
+ return@setOnClickListener
+ }
+ findNavController().navigate(
+ ListWeightFragmentDirections.actionNavListWeightToScanScalesDialog()
+ )
+ }
+
val adapter = WeightAdapter().apply {
onItemClick = {
findNavController().navigate(
@@ -152,15 +190,21 @@ class ListWeightFragment :
}
// Debug button
-// if (binding.debugRandomValues != null) {
-// binding.debugRandomValues.setOnClickListener {
-// viewModel.generateRandomValues()
-// }
-// binding.debugRandomValues.setOnLongClickListener {
-// viewModel.delete(viewModel.weights.value!!)
-// return@setOnLongClickListener true
-// }
-// }
+ if (BuildConfig.DEBUG) {
+ binding.debugRandomValues.visibility = View.VISIBLE
+ binding.debugRandomValues.setOnClickListener {
+ viewModel.generateRandomValues()
+ }
+ binding.debugRandomValues.setOnLongClickListener {
+ viewModel.delete(viewModel.weights.value!!)
+ return@setOnLongClickListener true
+ }
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ requireActivity().removeMenuProvider(menuProvider)
}
private fun updateGraph(list: List) {
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt
index e6a44c6..dc47292 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ListWeightViewModel.kt
@@ -10,15 +10,15 @@ import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.random.Random
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.launch
@HiltViewModel
class ListWeightViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
- private val settings: Configuration
+ settings: Configuration
) : BaseViewModel() {
private val _massUnit = MutableLiveData(Units.Mass.KILOGRAM)
@@ -60,7 +60,7 @@ class ListWeightViewModel @Inject internal constructor(
fun delete(list: List) {
viewModelScope.launch {
- for (item in list) weightRepository.deleteWeight(item)
+ weightRepository.deleteWeight(*list.toTypedArray())
}
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt
new file mode 100644
index 0000000..776050d
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesDialog.kt
@@ -0,0 +1,111 @@
+package com.dzeio.openhealth.ui.weight
+
+import android.annotation.SuppressLint
+import android.app.ProgressDialog
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.Toast
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.dzeio.openhealth.R
+import com.dzeio.openhealth.adapters.ItemAdapter
+import com.dzeio.openhealth.core.BaseDialog
+import com.dzeio.openhealth.databinding.DialogSearchBinding
+import com.dzeio.openhealth.devices.BluetoothLeGattDevice
+import com.dzeio.openhealth.devices.Device
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.launch
+
+@AndroidEntryPoint
+class ScanScalesDialog :
+ BaseDialog(ScanScalesViewModel::class.java) {
+
+ override val bindingInflater: (LayoutInflater) -> DialogSearchBinding =
+ DialogSearchBinding::inflate
+
+ override fun onBuilderInit(builder: MaterialAlertDialogBuilder) {
+ super.onBuilderInit(builder)
+
+ builder.apply {
+ setTitle(R.string.searching_scales)
+ setIcon(R.drawable.ic_outline_monitor_weight_24)
+ setNegativeButton(R.string.cancel) { dialog, _ ->
+ viewModel.stopScan()
+ dialog.cancel()
+ }
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ override fun onCreated() {
+ super.onCreated()
+ binding.search.visibility = View.GONE
+ binding.loading.visibility = View.VISIBLE
+
+ val adapter = ItemAdapter().apply {
+ onItemClick = { deviceAdapter ->
+ dialog!!.dismiss()
+ val device = deviceAdapter.value
+ viewModel.stopScan()
+ val progress = ProgressDialog(requireContext()).apply {
+ setTitle("Connecting & Fetching...")
+ setCancelable(false)
+ setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
+ show()
+ }
+ device.connect().addObserver { status ->
+ if (status === Device.ConnectionStatus.CONNECTED) {
+ device.fetchWeights().addObserver {
+ progress.progress = it.progress
+ progress.max = it.progressMax + 1
+
+ if (it.progress == it.progressMax) {
+ device.close()
+ Log.d("YAY", "${it.data}")
+ lifecycleScope.launch {
+ viewModel.addWeights(it.data)
+ progress.dismiss()
+ Toast.makeText(
+ requireContext(),
+ "Data synchonised with the remote device",
+ Toast.LENGTH_SHORT
+ ).show()
+ }
+ }
+ }
+ } else if (status === Device.ConnectionStatus.ERROR) {
+ progress.dismiss()
+ Toast.makeText(
+ requireContext(),
+ "An error occured while connecting...",
+ Toast.LENGTH_LONG
+ ).show()
+ }
+ }
+ }
+ }
+ binding.list.apply {
+ layoutManager = LinearLayoutManager(requireContext())
+ this.adapter = adapter
+ }
+
+ viewModel.devices.observe(this) {
+ if (it == null) {
+ adapter.clear()
+ return@observe
+ }
+ adapter.set(
+ it.map {
+ ItemAdapter.Item(
+ it,
+ it.name,
+ "${it.item!!.name} (${it.item!!.address})",
+ icon = R.drawable.ic_baseline_add_24
+ )
+ }
+ )
+ }
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesViewModel.kt
new file mode 100644
index 0000000..b658b9b
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/ScanScalesViewModel.kt
@@ -0,0 +1,42 @@
+package com.dzeio.openhealth.ui.weight
+
+import android.annotation.SuppressLint
+import androidx.annotation.RequiresPermission
+import com.dzeio.openhealth.core.BaseViewModel
+import com.dzeio.openhealth.data.weight.Weight
+import com.dzeio.openhealth.data.weight.WeightRepository
+import com.dzeio.openhealth.devices.BluetoothLeGattDevice
+import com.dzeio.openhealth.utils.Bluetooth
+import com.dzeio.openhealth.utils.Configuration
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.first
+
+@HiltViewModel
+class ScanScalesViewModel @Inject internal constructor(
+ private val bluetooth: Bluetooth,
+ private val weightRepository: WeightRepository,
+ config: Configuration
+) : BaseViewModel() {
+
+ @SuppressLint("MissingPermission")
+ @RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
+ val devices = BluetoothLeGattDevice.findDevices(bluetooth, config).toLiveData()
+
+ @RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
+ fun stopScan() {
+ bluetooth.stopScan()
+ }
+
+ suspend fun addWeights(weights: ArrayList) {
+ val current = weightRepository.getWeights().first()
+ val toAdd = arrayListOf()
+ for (weight in weights) {
+ if (current.find { it.equals(current) } != null) {
+ continue
+ }
+ toAdd.add(weight)
+ }
+ weightRepository.addAll(*toAdd.toTypedArray())
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialog.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialog.kt
index fc789f4..4ff45d6 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialog.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialog.kt
@@ -66,7 +66,6 @@ class WeightDialog :
binding.gram.maxValue = 9
binding.gram.minValue = 0
-
}
private fun setValue(value: Float) {
diff --git a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt
index c96fcbc..6738716 100644
--- a/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt
+++ b/app/src/main/java/com/dzeio/openhealth/ui/weight/WeightDialogViewModel.kt
@@ -10,14 +10,14 @@ import com.dzeio.openhealth.data.weight.WeightRepository
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.Configuration
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class WeightDialogViewModel @Inject internal constructor(
private val weightRepository: WeightRepository,
- private val settings: Configuration
+ settings: Configuration
) : BaseViewModel() {
private val _goalWeight = settings.getFloat(Settings.WEIGHT_GOAL)
@@ -40,7 +40,6 @@ class WeightDialogViewModel @Inject internal constructor(
weightRepository.lastWeight().collectLatest {
_weight.postValue(it)
}
-
}
}
}
diff --git a/app/src/main/java/com/dzeio/openhealth/units/Units.kt b/app/src/main/java/com/dzeio/openhealth/units/Units.kt
index fe29673..80abbae 100644
--- a/app/src/main/java/com/dzeio/openhealth/units/Units.kt
+++ b/app/src/main/java/com/dzeio/openhealth/units/Units.kt
@@ -40,7 +40,6 @@ object Units {
it.id == value
} ?: KILOGRAM
}
-
}
fun format(value: Float): Float {
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/Bluetooth.kt b/app/src/main/java/com/dzeio/openhealth/utils/Bluetooth.kt
new file mode 100644
index 0000000..d2519a0
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/utils/Bluetooth.kt
@@ -0,0 +1,148 @@
+package com.dzeio.openhealth.utils
+
+import android.annotation.SuppressLint
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.BluetoothGattCallback
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanResult
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.util.Log
+import android.widget.Toast
+import androidx.annotation.RequiresPermission
+import com.dzeio.openhealth.utils.polyfills.getBluetoothDevice
+
+class Bluetooth(
+ private val context: Context
+) {
+ companion object {
+ const val TAG = "Bluetooth"
+ }
+
+ private lateinit var adapter: BluetoothAdapter
+
+ init {
+ if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
+ throw Exception("Phone missing the Bluetooth feature")
+ }
+ try {
+ adapter = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter
+ } catch (e: Exception) {
+ Log.e(TAG, e.message ?: "error getting default adapter")
+ }
+ if (!adapter.isEnabled) {
+ Toast.makeText(context, "Bluetooth is not enabled", Toast.LENGTH_LONG).show()
+ Log.e(TAG, "Bluetooth is not enabled")
+ }
+ }
+
+ @SuppressLint("HardwareIds")
+ fun getAddress(): String {
+ return adapter.address
+ }
+
+ @RequiresPermission(value = "android.permission.BLUETOOTH_CONNECT")
+ fun getName(): String {
+ return adapter.name
+ }
+
+ /**
+ * Make the current phone discoverable through bluetooth scan
+ */
+// fun makeDeviceDiscoverable(time: Int = 600) {
+// val intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {
+// putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time)
+// }
+// activity.startActivityForResult(intent, 1)
+// }
+
+ fun getDiscoverableIntent(time: Int = 600): Intent {
+ return Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {
+ putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, time)
+ }
+ }
+
+ private lateinit var cb: (device: BluetoothDevice) -> Boolean
+
+ private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
+ @RequiresPermission(allOf = ["android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT"])
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action
+ if (BluetoothDevice.ACTION_FOUND == action) {
+ val device =
+ intent.getBluetoothDevice()
+ // val rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE).toInt()
+
+ if (device != null) {
+ Log.d(TAG, "Device found! (${device.name ?: device.address})")
+ val end = cb(device)
+ if (end) {
+ stopScan()
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Callback return boolean if true it stop scan
+ */
+ @RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
+ fun scanDevices(callback: (device: BluetoothDevice) -> Boolean): Boolean {
+ val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
+ context.registerReceiver(receiver, filter)
+ cb = callback
+ return adapter.startDiscovery()
+ }
+
+ private var leCallback: ((device: BluetoothDevice) -> Boolean)? = null
+ private val scanCallback = object : ScanCallback() {
+ @RequiresPermission(allOf = ["android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT"])
+ override fun onScanResult(callbackType: Int, result: ScanResult?) {
+ super.onScanResult(callbackType, result)
+ if (result != null) {
+ val device = result.device
+ Log.d(TAG, "Device found! (${device.name ?: device.address})")
+ val doStop = leCallback?.invoke(device)
+ if (doStop == true) {
+ stopScan()
+ }
+ }
+ }
+ }
+
+ /**
+ * Callback return boolean if true it stop scan
+ */
+ @RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
+ fun scanLeDevices(callback: (device: BluetoothDevice) -> Boolean) {
+ val pouet = adapter.bluetoothLeScanner
+ leCallback = callback
+ pouet.startScan(scanCallback)
+ }
+
+ @RequiresPermission(value = "android.permission.BLUETOOTH_SCAN")
+ fun stopScan() {
+ adapter.bluetoothLeScanner.stopScan(scanCallback)
+ adapter.cancelDiscovery()
+ try {
+ context.unregisterReceiver(receiver)
+ } catch (it: IllegalArgumentException) {
+ Log.i(TAG, "Seems like it was already unloaded", it)
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ fun connectGatt(
+ device: BluetoothDevice,
+ autoConnect: Boolean,
+ callback: BluetoothGattCallback
+ ) {
+ device.connectGatt(context, autoConnect, callback)
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt b/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt
index 26c96ce..1b2abce 100644
--- a/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt
+++ b/app/src/main/java/com/dzeio/openhealth/utils/Configuration.kt
@@ -1,7 +1,6 @@
package com.dzeio.openhealth.utils
import android.content.SharedPreferences
-import android.util.Log
import androidx.core.content.edit
import com.dzeio.openhealth.Application
import com.dzeio.openhealth.core.Observable
@@ -27,66 +26,66 @@ class Configuration(
fun getString(key: String): StringField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = StringField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as StringField
}
fun getLong(key: String): LongField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = LongField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as LongField
}
fun getBoolean(key: String): BooleanField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = BooleanField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as BooleanField
}
fun getInt(key: String): IntField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key is not cache, creating new instance")
cache[key] = IntField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as IntField
}
fun getFloat(key: String): FloatField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = FloatField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as FloatField
}
fun getStringSet(key: String): StringSetField {
if (cache[key] == null) {
- Log.d(TAG, "$key does not exist in cache, creating new instance")
+// Log.d(TAG, "$key does not exist in cache, creating new instance")
cache[key] = StringSetField(key)
} else {
- Log.d(TAG, "$key in cache")
+// Log.d(TAG, "$key in cache")
}
return cache[key] as StringSetField
}
override fun onSharedPreferenceChanged(u: SharedPreferences, key: String) {
- Log.d(TAG, "configuration update for key: $key")
+// Log.d(TAG, "configuration update for key: $key")
cache[key]?.needUpdate = true
cache[key]?.notifyObservers()
}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/DrawUtils.kt b/app/src/main/java/com/dzeio/openhealth/utils/DrawUtils.kt
index 871ae06..9b490c1 100644
--- a/app/src/main/java/com/dzeio/openhealth/utils/DrawUtils.kt
+++ b/app/src/main/java/com/dzeio/openhealth/utils/DrawUtils.kt
@@ -38,5 +38,4 @@ object DrawUtils {
val it = (if (isWidth) this.width else this.height) * multiplier
return it * value / 100
}
-
}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt b/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt
index 67d5e79..27aa103 100644
--- a/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt
+++ b/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt
@@ -9,11 +9,10 @@ import androidx.preference.PreferenceManager
import com.dzeio.openhealth.Settings
import java.util.Locale
-
/**
* Utils object for [Locale]
*
- * @see https://github.com/gunhansancar/ChangeLanguageExample/blob/master/app/src/main/java/com/gunhansancar/changelanguageexample/helper/LocaleHelper.java
+ * https://github.com/gunhansancar/ChangeLanguageExample/blob/master/app/src/main/java/com/gunhansancar/changelanguageexample/helper/LocaleHelper.java
*/
object LocaleUtils {
fun onAttach(context: Context): Context {
@@ -68,8 +67,10 @@ object LocaleUtils {
Locale.setDefault(locale)
val resources = context.resources
val configuration: Configuration = resources.configuration
+ @Suppress("DEPRECATION")
configuration.locale = locale
configuration.setLayoutDirection(locale)
+ @Suppress("DEPRECATION")
resources.updateConfiguration(configuration, resources.displayMetrics)
return context
}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt b/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt
index 3354bcf..4c0e838 100644
--- a/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt
+++ b/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt
@@ -36,4 +36,3 @@ object PermissionsManager {
return true
}
}
-
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/fields/IntEditTextPreference.kt b/app/src/main/java/com/dzeio/openhealth/utils/fields/IntEditTextPreference.kt
index f65d171..f620e5d 100644
--- a/app/src/main/java/com/dzeio/openhealth/utils/fields/IntEditTextPreference.kt
+++ b/app/src/main/java/com/dzeio/openhealth/utils/fields/IntEditTextPreference.kt
@@ -4,7 +4,6 @@ import android.content.Context
import android.text.InputType
import android.text.TextUtils
import android.util.AttributeSet
-import android.util.Log
import android.widget.EditText
import androidx.preference.EditTextPreference
@@ -48,7 +47,6 @@ class IntEditTextPreference : EditTextPreference, EditTextPreference.OnBindEditT
* @param text The text to save
*/
override fun setText(text: String?) {
-
val wasBlocking = shouldDisableDependents()
val pouet = Integer.parseInt(text.toString())
this.txt = text
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/polyfills/GattPolyfills.kt b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/GattPolyfills.kt
new file mode 100644
index 0000000..181e4bc
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/GattPolyfills.kt
@@ -0,0 +1,45 @@
+package com.dzeio.openhealth.utils.polyfills
+
+import android.bluetooth.BluetoothGatt
+import android.bluetooth.BluetoothGattCharacteristic
+import android.bluetooth.BluetoothGattDescriptor
+import android.os.Build
+import androidx.annotation.RequiresPermission
+
+@RequiresPermission(value = "android.permission.BLUETOOTH_CONNECT")
+fun BluetoothGatt.writeCharacteristicPoly(
+ characteristic: BluetoothGattCharacteristic,
+ value: ByteArray,
+ writeType: Int
+) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ this.writeCharacteristic(
+ characteristic,
+ value,
+ writeType
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ characteristic.value = value
+ @Suppress("DEPRECATION")
+ this.writeCharacteristic(characteristic)
+ }
+}
+
+@RequiresPermission(value = "android.permission.BLUETOOTH_CONNECT")
+fun BluetoothGatt.writeDescriptorPoly(
+ descriptor: BluetoothGattDescriptor,
+ value: ByteArray
+) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ this.writeDescriptor(
+ descriptor,
+ value
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ descriptor.value = value
+ @Suppress("DEPRECATION")
+ this.writeDescriptor(descriptor)
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/polyfills/IntentPolyfills.kt b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/IntentPolyfills.kt
new file mode 100644
index 0000000..6b46218
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/IntentPolyfills.kt
@@ -0,0 +1,14 @@
+package com.dzeio.openhealth.utils.polyfills
+
+import android.bluetooth.BluetoothDevice
+import android.content.Intent
+import android.os.Build
+
+fun Intent.getBluetoothDevice(): BluetoothDevice? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ this.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java)
+ } else {
+ @Suppress("DEPRECATION")
+ this.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
+ }
+}
diff --git a/app/src/main/java/com/dzeio/openhealth/utils/polyfills/ServicePolyfills.kt b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/ServicePolyfills.kt
new file mode 100644
index 0000000..d82cb7d
--- /dev/null
+++ b/app/src/main/java/com/dzeio/openhealth/utils/polyfills/ServicePolyfills.kt
@@ -0,0 +1,24 @@
+package com.dzeio.openhealth.utils.polyfills
+
+import android.app.Service
+import android.os.Build
+
+enum class NotificationBehavior {
+ REMOVE,
+ DETACH
+}
+
+fun Service.stopForegroundPoly(notificationBehavior: NotificationBehavior) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ stopForeground(
+ if (notificationBehavior === NotificationBehavior.REMOVE) {
+ Service.STOP_FOREGROUND_REMOVE
+ } else {
+ Service.STOP_FOREGROUND_DETACH
+ }
+ )
+ } else {
+ @Suppress("DEPRECATION")
+ stopForeground(notificationBehavior == NotificationBehavior.REMOVE)
+ }
+}
diff --git a/app/src/main/res/drawable/ic_bluetooth.xml b/app/src/main/res/drawable/ic_bluetooth.xml
new file mode 100644
index 0000000..59d56fd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_bluetooth.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/layout/dialog_search.xml b/app/src/main/res/layout/dialog_search.xml
new file mode 100644
index 0000000..5012a47
--- /dev/null
+++ b/app/src/main/res/layout/dialog_search.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
index 8d6c621..709783f 100644
--- a/app/src/main/res/layout/fragment_home.xml
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -7,6 +7,13 @@
android:orientation="vertical"
tools:context=".ui.home.HomeFragment">
+
+
diff --git a/app/src/main/res/layout/fragment_list_weight.xml b/app/src/main/res/layout/fragment_list_weight.xml
index 47df57c..4efd789 100644
--- a/app/src/main/res/layout/fragment_list_weight.xml
+++ b/app/src/main/res/layout/fragment_list_weight.xml
@@ -6,6 +6,62 @@
android:orientation="vertical"
android:layout_height="wrap_content">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_list.xml b/app/src/main/res/layout/item_list.xml
new file mode 100644
index 0000000..09c4dc5
--- /dev/null
+++ b/app/src/main/res/layout/item_list.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml
index ed403ac..5625f22 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -27,6 +27,9 @@
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6e6f09e..0296bd3 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -68,4 +68,5 @@
%1$s (%2$.0f kcal)
%1$d steps
It seems that we can\'t communicate with OpenFoodFact, please retry later
+ Searchin Scales
diff --git a/app/src/test/java/com/dzeio/openhealth/ExampleUnitTest.kt b/app/src/test/java/com/dzeio/openhealth/ExampleUnitTest.kt
index 8f371e0..e3197c7 100644
--- a/app/src/test/java/com/dzeio/openhealth/ExampleUnitTest.kt
+++ b/app/src/test/java/com/dzeio/openhealth/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package com.dzeio.openhealth
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index 6cfe8ca..1a88f96 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,14 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
dependencies {
- // Data Injection
- classpath("com.google.dagger:hilt-android-gradle-plugin:2.44.2")
-
// Safe Navigation
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3")
// OSS licenses
classpath("com.google.android.gms:oss-licenses-plugin:0.10.6")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10")
+ }
+ repositories {
+ mavenCentral()
}
}
@@ -19,7 +20,10 @@ plugins {
id("com.android.library") version "7.4.0" apply false
// add kotlin compatibility :>
- id("org.jetbrains.kotlin.android") version "1.8.0" apply false
+ id("org.jetbrains.kotlin.android") version "1.8.10" apply false
+
+ // Hilt
+ id("com.google.dagger.hilt.android") version "2.44" apply false
}
// Cleanup the build directories