1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-04-25 12:22:15 +00:00

feat: updated

This commit is contained in:
Florian Bouillon 2023-01-19 17:20:14 +01:00
parent 7875271b7e
commit 357024770a
13 changed files with 110 additions and 379 deletions

View File

@ -130,7 +130,7 @@ android {
dependencies {
// Dzeio Charts
implementation("com.dzeio:charts:edd78e87e1")
implementation("com.dzeio:charts:cbd5f57f8d")
// Dzeio Crash Handler
implementation("com.dzeio:crashhandler:1.0.1")
@ -139,7 +139,7 @@ dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.7.0-alpha01")
implementation("javax.inject:javax.inject:1")
implementation("com.google.android.material:material:1.8.0-rc01")
implementation("com.google.android.material:material:1.9.0-alpha01")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
@ -169,18 +169,15 @@ dependencies {
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
// Graph
implementation("com.github.PhilJay:MPAndroidChart:v3.1.0")
// Hilt
implementation("com.google.dagger:hilt-android:2.44.2")
kapt("com.google.dagger:hilt-compiler:2.44.2")
// ROOM
implementation("androidx.room:room-runtime:2.4.3")
kapt("androidx.room:room-compiler:2.4.3")
implementation("androidx.room:room-ktx:2.4.3")
testImplementation("androidx.room:room-testing:2.4.3")
implementation("androidx.room:room-runtime:2.5.0")
kapt("androidx.room:room-compiler:2.5.0")
implementation("androidx.room:room-ktx:2.5.0")
testImplementation("androidx.room:room-testing:2.5.0")
// Futures
implementation("com.google.guava:guava:31.1-jre")

View File

@ -1,150 +0,0 @@
package com.dzeio.openhealth.graphs
import android.graphics.Color
import android.view.View
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.ChartUtils
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.LimitLine
import com.github.mikephil.charting.components.YAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.google.android.material.color.MaterialColors
import kotlin.math.max
import kotlin.math.min
/**
* TODO: Migrate to DzeioCharts when it is ready
*
* Setup the mikephil Chart for the Weight
*/
object WeightChart {
fun setup(
chart: LineChart,
view: View,
data: List<Weight>,
modifier: Units.Mass,
goal: Float?,
limit: Boolean = true
) {
ChartUtils.lineChartSetup(
chart,
MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorPrimary
),
MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorOnBackground
)
)
if (data.isEmpty()) {
return
}
// Axis Max/Min
var axisMin = max(data.minOf { it.weight } - 10, 0f)
var axisMax = data.maxOf { it.weight } + 10
if (goal != null) {
axisMax = max(axisMax, goal)
axisMin = min(axisMin, goal)
}
// Average calculation
val averageCalculation = min(30, max(3, data.size / 2))
val isEven = averageCalculation % 2 == 1
val midValue = averageCalculation / 2
val averageYs = data.mapIndexed { index, entry ->
var minItem = index - midValue
var maxItem = index + if (!isEven) midValue + 1 else midValue
val lastEntry = data.size - 1
if (minItem < 0) {
maxItem += kotlin.math.abs(minItem)
minItem = 0
}
if (maxItem >= lastEntry) {
val diff = maxItem - lastEntry
minItem = max(0, minItem - diff)
maxItem -= diff
}
var average = 0f
for (i in minItem..maxItem) {
average += data[i].weight
}
return@mapIndexed Entry(
entry.timestamp.toFloat(),
(average / (maxItem - minItem + 1)) * modifier.modifier
)
}
val rawData = ChartUtils.lineDataSet(
LineDataSet(
data.mapIndexed { _, weight ->
return@mapIndexed Entry(
weight.timestamp.toFloat(),
weight.weight * modifier.modifier
)
},
"Weight"
)
).apply {
axisDependency = YAxis.AxisDependency.RIGHT
}
val averageData = ChartUtils.lineDataSet(LineDataSet(averageYs, "Average")).apply {
axisDependency = YAxis.AxisDependency.RIGHT
color = Color.GREEN
}
val entries = ArrayList<Entry>()
for (item in data) {
entries.add(
Entry(
item.timestamp.toFloat(),
item.weight * modifier.modifier
)
)
}
chart.apply {
this.data = LineData(rawData, averageData)
val twoWeeks = (data[data.size - 1].timestamp - data[0].timestamp) > 1290000000f
if (twoWeeks && limit) {
// idk what I did but it works lol
setVisibleXRange(
0f, data[data.size - 1].timestamp / 1000f
)
axisRight.axisMinimum = axisMin * modifier.modifier
axisRight.axisMaximum = axisMax * modifier.modifier
// BIS... :(
// Also it invalidate the view so I don't have to call invalidate
moveViewToX(data[data.size - 1].timestamp - 1290000000f)
}
if (goal != null) {
val limit = LimitLine(goal * modifier.modifier)
limit.lineColor = Color.RED
val dash = 30f
limit.enableDashedLine(dash, dash, 1f)
limit.lineWidth = 1f
limit.textColor = Color.BLACK
axisRight.removeAllLimitLines()
axisRight.addLimitLine(limit)
}
invalidate()
}
}
}

View File

@ -3,7 +3,6 @@ package com.dzeio.openhealth.ui
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
@ -11,6 +10,7 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.WindowInsets
import android.view.WindowManager
import androidx.core.view.WindowCompat
import androidx.core.view.updatePadding
@ -21,7 +21,6 @@ import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.dzeio.openhealth.Application
import com.dzeio.openhealth.R
import com.dzeio.openhealth.core.BaseActivity
import com.dzeio.openhealth.databinding.ActivityMainBinding
@ -35,7 +34,7 @@ import dagger.hilt.android.AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>() {
companion object {
const val TAG = "${Application.TAG}/MainActivity"
val TAG: String = this::class.java.simpleName
}
private lateinit var appBarConfiguration: AppBarConfiguration
@ -48,7 +47,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_OpenHealth_NoActionBar)
super.onCreate(savedInstanceState)
}
override fun onCreated(savedInstanceState: Bundle?) {
@ -58,7 +56,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
// Comportement chelou API 28-
// Comportement normal 31+
// do not do the cool status/navigation bars for API 29 & 30
if (Build.VERSION.SDK_INT != Build.VERSION_CODES.R && Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) {
// allow to put the content behind the status bar & Navigation bar (one of them at least lul)
@ -66,25 +63,23 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
// Make the color of the navigation bar semi-transparent
// window.navigationBarColor = Color.TRANSPARENT
// Make the color of the status bar transparent
// window.statusBarColor = Color.TRANSPARENT
// Apply the previous changes
// window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
// Update toolbar height with the statusbar size included
// ALSO: make both the status/navigation bars transparent (WHYYYYYYY)
val toolbarHeight = binding.toolbar.layoutParams.height
window.decorView.setOnApplyWindowInsetsListener { _, insets ->
val statusBarSize = insets.systemWindowInsetTop
// Use getInsets(int) with WindowInsets.Type.systemBars() instead.
val statusBarSize = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
insets.getInsets(WindowInsets.Type.systemBars()).top
} else {
insets.systemWindowInsetTop
}
// Add padding to the toolbar (YaY I know how something works)
binding.toolbar.updatePadding(top = statusBarSize)
binding.toolbar.layoutParams.height = toolbarHeight + statusBarSize
return@setOnApplyWindowInsetsListener insets
}
// normally makes sure icons are at the correct color but idk if it works
// normally makes sure icons are at the correct color
when (this.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) {
Configuration.UI_MODE_NIGHT_YES -> {
WindowCompat.getInsetsController(window, window.decorView).apply {
@ -121,25 +116,17 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.bottomNav.setupWithNavController(navController)
// registerForActivityResult(ActivityResultContracts.RequestPermission()) {
//
// }
// .launch(Manifest.permission.ACTIVITY_RECOGNITION)
createNotificationChannel()
// Services
WaterReminderWorker.setup(this)
// StepCountService.setup(this)
ServiceUtils.startService(this, OpenHealthService::class.java)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.main, menu)
return true
return super.onCreateOptionsMenu(menu)
}
override fun onSupportNavigateUp(): Boolean =
@ -149,22 +136,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
NavigationUI.onNavDestinationSelected(item, navController) ||
super.onOptionsItemSelected(item)
@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.d("MainActivity", "onActivityResult $requestCode $resultCode")
for (fragment in supportFragmentManager.primaryNavigationFragment!!.childFragmentManager.fragments) {
fragment.onActivityResult(requestCode, resultCode, data)
}
}
private fun createNotificationChannel() {
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
for (channel in NotificationChannels.values()) {
Log.d("MainActivity", channel.channelName)
Log.d(TAG, channel.channelName)
try {
notificationManager.createNotificationChannel(
NotificationChannel(
@ -174,7 +152,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
)
)
} catch (e: Exception) {
Log.e("MainActivity", "Error Creating Notification Channel", e)
Log.e(TAG, "Error Creating Notification Channel", e)
}
}
}

View File

@ -9,15 +9,16 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import com.dzeio.charts.Entry
import com.dzeio.charts.series.LineSerie
import com.dzeio.openhealth.core.BaseFragment
import com.dzeio.openhealth.data.water.Water
import com.dzeio.openhealth.data.weight.Weight
import com.dzeio.openhealth.databinding.FragmentHomeBinding
import com.dzeio.openhealth.graphs.WeightChart
import com.dzeio.openhealth.ui.weight.WeightDialog
import com.dzeio.openhealth.units.Units
import com.dzeio.openhealth.utils.DrawUtils
import com.dzeio.openhealth.utils.ChartUtils
import com.dzeio.openhealth.utils.DrawUtils
import com.google.android.material.color.MaterialColors
import dagger.hilt.android.AndroidEntryPoint
import kotlin.math.max
@ -89,18 +90,11 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
findNavController().navigate(HomeFragmentDirections.actionNavHomeToNavWaterHome())
}
// Make a line Chart using the graph library
ChartUtils.lineChartSetup(
binding.weightGraph,
MaterialColors.getColor(
requireView(),
com.google.android.material.R.attr.colorPrimary
),
MaterialColors.getColor(
requireView(),
com.google.android.material.R.attr.colorOnBackground
)
)
binding.weightGraph.apply {
val serie = LineSerie(this)
ChartUtils.materielTheme(this, requireView())
series = arrayListOf(serie)
}
// Update the water intake Graph when the water intake changes
viewModel.water.observe(viewLifecycleOwner) {
@ -147,13 +141,28 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
* Function that update the graph for the weight
*/
private fun updateGraph(list: List<Weight>) {
WeightChart.setup(
binding.weightGraph,
requireView(),
list,
viewModel.massUnit.value!!,
viewModel.goalWeight.value
)
val chart = binding.weightGraph
val serie = chart.series[0] as LineSerie
val entries: ArrayList<Entry> = arrayListOf()
list.forEach {
entries.add(
Entry(
it.timestamp.toDouble(),
it.weight
)
)
}
serie.entries = entries
if (list.isEmpty()) {
chart.xAxis.x = 0.0
} else {
chart.xAxis.x = list[0].timestamp.toDouble()
}
chart.refresh()
}
/**
@ -165,7 +174,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
* function that update the water count in the home page
*/
private fun updateWater(newValue: Int) {
// get the current Unit
val waterUnit =
Units.Volume.find(settings.getString("water_unit", "milliliter") ?: "Milliliter")
@ -193,7 +201,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
height = binding.background.height
}
// Prepare the update animation
val animator = ValueAnimator.ofInt(
this.oldValue.toInt(),
@ -201,7 +208,6 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentHomeBinding>(HomeViewMo
)
animator.duration = 300 // ms
animator.addUpdateListener {
this.oldValue = (it.animatedValue as Int).toFloat()
val value = 100 * it.animatedValue as Int / viewModel.dailyWaterIntake.toFloat()

View File

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.dzeio.charts.Entry
import com.dzeio.charts.axis.Line
import com.dzeio.charts.series.BarSerie
import com.dzeio.openhealth.Application
import com.dzeio.openhealth.adapters.StepsAdapter
@ -18,6 +19,7 @@ import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import kotlin.math.roundToInt
@AndroidEntryPoint
class StepsHomeFragment :
@ -58,27 +60,33 @@ class StepsHomeFragment :
chart.apply {
ChartUtils.materielTheme(chart, requireView())
yAxis.apply {
onValueFormat = { value -> "${value.toInt()}" }
setYMin(0f)
}
xAxis.apply {
dataWidth = 604800000.0
textPaint.textSize = 32f
onValueFormat = onValueFormat@{
val formatter = DateFormat.getDateTimeInstance(
DateFormat.SHORT,
val formatter = DateFormat.getDateInstance(
DateFormat.SHORT,
Locale.getDefault()
)
return@onValueFormat formatter.format(Date(it.toLong()))
}
}
annotator.annotationTitleFormat = { "${it.y.roundToInt()} steps" }
annotator.annotationSubTitleFormat = annotationSubTitleFormat@{
val formatter = DateFormat.getDateInstance(
DateFormat.SHORT,
Locale.getDefault()
)
return@annotationSubTitleFormat formatter.format(Date(it.x.toLong()))
}
}
viewModel.goal.observe(viewLifecycleOwner) {
if (it != null) {
chart.yAxis.addLine(it.toFloat())
chart.yAxis.addLine(it.toFloat(), Line(true))
chart.refresh()
}
}
@ -120,7 +128,6 @@ class StepsHomeFragment :
chart.xAxis.x = chart.xAxis.getXMin()
chart.refresh()
}
}

View File

@ -110,7 +110,7 @@ class ListWeightFragment :
xAxis.apply {
// 7 day history
// increment = (7 * 24 * 60 * 60 * 1000).toDouble()
dataWidth = (7 * 24 * 60 * 60 * 1000).toDouble()
textPaint.color = MaterialColors.getColor(
requireView(),
com.google.android.material.R.attr.colorOnPrimaryContainer
@ -124,7 +124,6 @@ class ListWeightFragment :
)
return@onValueFormat formatter.format(Date(it.toLong()))
}
}
}

View File

@ -1,51 +0,0 @@
package com.dzeio.openhealth.utils
import android.content.Context
import android.graphics.Bitmap
import java.io.File
import java.io.RandomAccessFile
import java.nio.channels.FileChannel
object BitmapUtils {
/**
* Stolen from StackOverflow but I don't remember where...
*
* Convert an immutable Bitmap to a mutable one if possible
*/
fun convertToMutable(context: Context, imgIn: Bitmap): Bitmap? {
val width = imgIn.width
val height = imgIn.height
val type = imgIn.config
var outputFile: File? = null
val outputDir = context.cacheDir
try {
outputFile = File.createTempFile(
System.currentTimeMillis().toString(),
null,
outputDir
)
outputFile.deleteOnExit()
val randomAccessFile = RandomAccessFile(outputFile, "rw")
val channel = randomAccessFile.channel
val map = channel.map(
FileChannel.MapMode.READ_WRITE,
0,
(imgIn.rowBytes * height).toLong()
)
imgIn.copyPixelsToBuffer(map)
imgIn.recycle()
val result = Bitmap.createBitmap(width, height, type)
map.position(0)
result.copyPixelsFromBuffer(map)
channel.close()
randomAccessFile.close()
outputFile.delete()
return result
} catch (e: Exception) {
} finally {
outputFile?.delete()
}
return null
}
}

View File

@ -2,117 +2,51 @@ package com.dzeio.openhealth.utils
import android.view.View
import com.dzeio.charts.ChartView
import com.dzeio.charts.components.Annotation
import com.dzeio.charts.series.BarSerie
import com.dzeio.charts.series.LineSerie
import com.github.mikephil.charting.charts.BarLineChartBase
import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.components.AxisBase
import com.github.mikephil.charting.components.Description
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet
import com.google.android.material.color.MaterialColors
import java.text.SimpleDateFormat
import java.text.DateFormat
import java.util.Date
import java.util.Locale
import kotlin.math.roundToLong
/**
* Utils object to create graphics using the mikephil charting library
*
* TODO: migrate to DzeioCharts once it is ready
* Utils object to create Charts
*/
object ChartUtils {
fun lineChartSetup(chart: LineChart, mainColor: Int, textColor: Int) {
barLineChartSetup(chart, mainColor, textColor)
// chart.isAutoScaleMinMaxEnabled = true
}
fun lineDataSet(lineDataSet: LineDataSet): LineDataSet {
return lineDataSet.apply {
setDrawCircles(false)
setDrawCircleHole(false)
mode = LineDataSet.Mode.HORIZONTAL_BEZIER
}
}
private fun <T : BarLineScatterCandleBubbleData<out IBarLineScatterCandleBubbleDataSet<out Entry>>?> barLineChartSetup(
chart: BarLineChartBase<T>,
mainColor: Int,
textColor: Int
) {
chart.apply {
// Setup
legend.isEnabled = true
description = Description().apply { isEnabled = false }
xAxis.apply {
valueFormatter = DateValueFormatter()
position = XAxis.XAxisPosition.BOTTOM
setDrawGridLines(false)
setLabelCount(3, true)
this.textColor = textColor
// setDrawGridLines(false)
// setDrawZeroLine(false)
setDrawAxisLine(false)
disableGridDashedLine()
invalidateOutline()
}
axisLeft.apply {
axisMinimum = 0f
isEnabled = false
axisLineColor = mainColor
this.textColor = textColor
setDrawZeroLine(false)
setLabelCount(0, true)
setDrawGridLines(false)
setDrawBorders(false)
}
axisRight.apply {
axisMinimum = 0f
this.textColor = textColor
setLabelCount(4, true)
}
setNoDataTextColor(textColor)
legend.isEnabled = false
isDragEnabled = true
// isScaleYEnabled = false
description = Description().apply { isEnabled = false }
isScaleXEnabled = true
setPinchZoom(false)
setDrawGridBackground(false)
setDrawBorders(false)
}
}
class DateValueFormatter(
private val transformer: Int = 1
) : ValueFormatter() {
override fun getAxisLabel(value: Float, axis: AxisBase?): String {
return SimpleDateFormat(
"yyyy-MM-dd",
Locale.getDefault()
).format(Date(value.toLong() * transformer))
// return super.getAxisLabel(value, axis)
}
}
/**
* Apply Material theme to a DzeioChart [ChartView]
*/
fun materielTheme(chart: ChartView, view: View) {
val errorColor = MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorError
)
chart.apply {
annotator.apply {
backgroundPaint.color = MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorBackgroundFloating
)
titlePaint.color = MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorOnBackground
)
subTitlePaint.color = MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorOnBackground
)
orientation = Annotation.Orientation.VERTICAL
annotationTitleFormat = { it.y.roundToLong().toString() }
annotationSubTitleFormat = annotationSubTitleFormat@{
val formatter = DateFormat.getDateTimeInstance(
DateFormat.SHORT,
DateFormat.SHORT,
Locale.getDefault()
)
return@annotationSubTitleFormat formatter.format(Date(it.x.roundToLong()))
}
}
yAxis.apply {
textLabel.color = MaterialColors.getColor(
view,
@ -122,7 +56,10 @@ object ChartUtils {
view,
com.google.android.material.R.attr.colorOnPrimaryContainer
)
goalLinePaint.color = errorColor
goalLinePaint.color = MaterialColors.getColor(
view,
com.google.android.material.R.attr.colorError
)
}
xAxis.apply {

View File

@ -155,7 +155,14 @@ class Configuration(
private val defaultValue: Float = -1f
) : Field<Float?>(defaultValue) {
override fun exists(): Boolean = prefs.contains(key)
override fun internalGet(): Float = prefs.getFloat(key, defaultValue)
override fun internalGet(): Float {
return try {
prefs.getFloat(key, defaultValue)
} catch (e: ClassCastException) {
val it = prefs.getString(key, "")
it?.toFloatOrNull() ?: defaultValue
}
}
override fun internalSet(value: Float?) =
prefs.edit { if (value == null) remove(key) else putFloat(key, value) }
}

View File

@ -4,7 +4,7 @@ import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.util.Log
import com.dzeio.openhealth.ui.MainActivity
import com.dzeio.openhealth.Application
/**
* Utils class for services
@ -20,11 +20,11 @@ object ServiceUtils {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
for (runninService in activityManager.getRunningServices(Integer.MAX_VALUE)) {
if (service.name.equals(runninService.service.className)) {
Log.w(MainActivity.TAG, "Service already existing, not starting again")
Log.w(Application.TAG, "Service already existing, not starting again")
return
}
}
Log.i(MainActivity.TAG, "Starting service ${service.name}")
Log.i(Application.TAG, "Starting service ${service.name}")
Intent(context, service).also { intent -> context.startService(intent) }
}
}

View File

@ -65,6 +65,7 @@
android:id="@+id/bottom_nav"
android:layout_width="match_parent"
android:fitsSystemWindows="false"
app:labelVisibilityMode="labeled"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"

View File

@ -303,10 +303,11 @@
</LinearLayout>
<com.github.mikephil.charting.charts.LineChart
<com.dzeio.charts.ChartView
android:id="@+id/weight_graph"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="8dp"
android:minHeight="200dp" />
</LinearLayout>

View File

@ -18,7 +18,6 @@
<item
android:id="@+id/nav_extensions"
android:enabled="false"
android:title="@string/menu_extensions"
android:icon="@drawable/ic_outline_account_circle_24"/>
</menu>