From b5fa5c0673303883d2d11db5d9545f0e251b3d28 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sun, 1 Mar 2020 21:42:50 +0000 Subject: [PATCH] Code separation and cleanup for future testing --- .../com/rtbishop/look4sat/MainViewModel.kt | 186 +++++------------- .../com/rtbishop/look4sat/di/UtilityModule.kt | 45 +++++ .../com/rtbishop/look4sat/ui/MainActivity.kt | 4 +- .../rtbishop/look4sat/ui/MapViewFragment.kt | 10 +- .../rtbishop/look4sat/ui/PassListFragment.kt | 4 +- .../rtbishop/look4sat/ui/PolarViewFragment.kt | 4 +- .../look4sat/ui/adapters/SatPassAdapter.kt | 4 +- .../rtbishop/look4sat/utility/DataManager.kt | 112 +++++++++++ .../rtbishop/look4sat/utility/PrefsManager.kt | 92 +++++++++ build.gradle | 2 +- 10 files changed, 311 insertions(+), 152 deletions(-) create mode 100644 app/src/main/java/com/rtbishop/look4sat/di/UtilityModule.kt create mode 100644 app/src/main/java/com/rtbishop/look4sat/utility/DataManager.kt create mode 100644 app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt diff --git a/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt index 3888dbc2..27b62438 100644 --- a/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt @@ -20,11 +20,6 @@ package com.rtbishop.look4sat import android.app.Application -import android.content.Context -import android.content.SharedPreferences -import android.location.LocationManager -import android.util.Log -import androidx.core.content.edit import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData @@ -36,103 +31,58 @@ import com.rtbishop.look4sat.predict4kotlin.PassPredictor import com.rtbishop.look4sat.repo.Repository import com.rtbishop.look4sat.repo.SatPass import com.rtbishop.look4sat.repo.Transmitter +import com.rtbishop.look4sat.utility.DataManager +import com.rtbishop.look4sat.utility.PrefsManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.io.FileNotFoundException import java.io.IOException -import java.io.ObjectInputStream -import java.io.ObjectOutputStream import java.util.* import javax.inject.Inject class MainViewModel(application: Application) : AndroidViewModel(application) { - private val tag = "MainViewModel" - private val app = application - private val keyHours = application.getString(R.string.pref_hours_ahead_key) - private val keyMinEl = application.getString(R.string.pref_min_el_key) - private val keyLat = application.getString(R.string.pref_lat_key) - private val keyLon = application.getString(R.string.pref_lon_key) - private val keyAlt = application.getString(R.string.pref_alt_key) - private val keyDelay = application.getString(R.string.pref_refresh_rate_key) - private val tleMainListFileName = "tleFile.txt" - private val tleSelectionFileName = "tleSelection" - - private val _debugMessage = MutableLiveData() - val debugMessage: LiveData = _debugMessage - - private val _satPassList = MutableLiveData>() - val satPassList: LiveData> = _satPassList - - private val _gsp = MutableLiveData() - val gsp: LiveData = _gsp - private val urlList = listOf("https://celestrak.com/NORAD/elements/active.txt") - + private val _satPassList = MutableLiveData>() + private val _debugMessage = MutableLiveData() + private val _gsp = MutableLiveData() private var calculationJob: Job? = null - @Inject - lateinit var locationManager: LocationManager - @Inject - lateinit var preferences: SharedPreferences @Inject lateinit var repository: Repository - - lateinit var tleMainList: List - lateinit var tleSelection: MutableList + @Inject + lateinit var dataManager: DataManager + @Inject + lateinit var prefsManager: PrefsManager init { (app as Look4SatApp).appComponent.inject(this) - loadDataFromDisk() + setGroundStationPosition() } - val delay: Long - get() = preferences.getString(keyDelay, "3000")!!.toLong() + var tleMainList = dataManager.loadTleList() + var tleSelection = dataManager.loadSelectionList() - val hoursAhead: Int - get() = preferences.getInt(keyHours, 8) - - val minEl: Double - get() = preferences.getDouble(keyMinEl, 16.0) - - fun setGroundStationPosition() { - val lat = preferences.getString(keyLat, "0.0")!!.toDouble() - val lon = preferences.getString(keyLon, "0.0")!!.toDouble() - val alt = preferences.getString(keyAlt, "0.0")!!.toDouble() - _gsp.postValue(GroundStationPosition(lat, lon, alt)) - } + fun getGSP(): LiveData = _gsp + fun getDebugMessage(): LiveData = _debugMessage + fun getSatPassList(): LiveData> = _satPassList + fun getRefreshRate() = prefsManager.getRefreshRate() + fun getHoursAhead() = prefsManager.getHoursAhead() + fun getMinElevation() = prefsManager.getMinElevation() + fun setGroundStationPosition() = _gsp.postValue(prefsManager.getGroundStationPosition()) fun updateLocation() { - val passiveProvider = LocationManager.PASSIVE_PROVIDER - try { - val location = locationManager.getLastKnownLocation(passiveProvider) - - val lat = location?.latitude ?: 0.0 - val lon = location?.longitude ?: 0.0 - val alt = location?.altitude ?: 0.0 - - preferences.edit { - putString(keyLat, lat.toString()) - putString(keyLon, lon.toString()) - putString(keyAlt, alt.toString()) - apply() - } - _gsp.postValue(GroundStationPosition(lat, lon, alt)) - _debugMessage.postValue(app.getString(R.string.update_loc_success)) - } catch (e: SecurityException) { - _debugMessage.postValue(app.getString(R.string.err_no_permissions)) + dataManager.getLastKnownLocation()?.let { + prefsManager.setGroundStationPosition(it) + _gsp.postValue(it) } } fun setPassPrefs(hoursAhead: Int, minEl: Double) { - preferences.edit { - putInt(keyHours, hoursAhead) - putDouble(keyMinEl, minEl) - apply() - } + prefsManager.setHoursAhead(hoursAhead) + prefsManager.setMinElevation(minEl) } fun updateAndSaveTleFile() { @@ -140,12 +90,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { try { val inputStream = repository.getStreamForUrl(urlList) val tleList = TLE.importSat(inputStream).apply { sortBy { it.name } } - val fileOutStream = app.openFileOutput(tleMainListFileName, Context.MODE_PRIVATE) - ObjectOutputStream(fileOutStream).apply { - writeObject(tleList) - flush() - close() - } + dataManager.saveTleList(tleList) tleMainList = tleList tleSelection = mutableListOf() _debugMessage.postValue(app.getString(R.string.update_tle_success)) @@ -168,35 +113,21 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { fun updateAndSaveSelectionList(list: MutableList) { tleSelection = list - try { - val fileOutputStream = app.openFileOutput(tleSelectionFileName, Context.MODE_PRIVATE) - ObjectOutputStream(fileOutputStream).apply { - writeObject(list) - flush() - close() - } - } catch (exception: IOException) { - _debugMessage.postValue(exception.toString()) - } + dataManager.saveSelectionList(list) } fun getPasses() { calculationJob?.cancel() - val passList = mutableListOf() - val dateNow = Date() - val dateFuture = Calendar.getInstance().let { - it.time = dateNow - it.add(Calendar.HOUR, hoursAhead) - it.time - } + var passList = mutableListOf() calculationJob = viewModelScope.launch { if (tleMainList.isNotEmpty() && tleSelection.isNotEmpty()) { withContext(Dispatchers.Default) { + val dateNow = Date() tleSelection.forEach { indexOfSelection -> val tle = tleMainList[indexOfSelection] try { - val predictor = PassPredictor(tle, gsp.value!!) - val passes = predictor.getPasses(dateNow, hoursAhead, true) + val predictor = PassPredictor(tle, getGSP().value!!) + val passes = predictor.getPasses(dateNow, getHoursAhead(), true) passes.forEach { passList.add(SatPass(tle, predictor, it)) } @@ -206,10 +137,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { _debugMessage.postValue(app.getString(R.string.err_sat_wont_pass)) } } - passList.removeAll { it.pass.startTime.after(dateFuture) } - passList.removeAll { it.pass.endTime.before(dateNow) } - passList.removeAll { it.pass.maxEl < minEl } - passList.sortBy { it.pass.startTime } + passList = filterAndSortList(passList, getHoursAhead()) } _satPassList.postValue(passList) } else { @@ -219,42 +147,24 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } } + private fun filterAndSortList( + list: MutableList, + hoursAhead: Int + ): MutableList { + val dateNow = Date() + val dateFuture = Calendar.getInstance().let { + it.time = dateNow + it.add(Calendar.HOUR, hoursAhead) + it.time + } + list.removeAll { it.pass.startTime.after(dateFuture) } + list.removeAll { it.pass.endTime.before(dateNow) } + list.removeAll { it.pass.maxEl < getMinElevation() } + list.sortBy { it.pass.startTime } + return list + } + suspend fun getTransmittersForSat(id: Int): List { return repository.getTransmittersForSat(id) } - - @Suppress("UNCHECKED_CAST") - private fun loadDataFromDisk() { - tleMainList = try { - val tleStream = app.openFileInput(tleMainListFileName) - val tleList = ObjectInputStream(tleStream).readObject() - tleList as List - } catch (exception: FileNotFoundException) { - Log.w(tag, app.getString(R.string.err_no_tle_file)) - emptyList() - } catch (exception: IOException) { - Log.w(tag, exception.toString()) - emptyList() - } - tleSelection = try { - val selectionStream = app.openFileInput(tleSelectionFileName) - val selectionList = ObjectInputStream(selectionStream).readObject() - selectionList as MutableList - } catch (exception: FileNotFoundException) { - Log.w(tag, app.getString(R.string.err_no_selection_file)) - mutableListOf() - } catch (exception: IOException) { - Log.w(tag, exception.toString()) - mutableListOf() - } - setGroundStationPosition() - } -} - -fun SharedPreferences.Editor.putDouble(key: String, double: Double) { - putLong(key, double.toRawBits()) -} - -fun SharedPreferences.getDouble(key: String, default: Double): Double { - return Double.fromBits(getLong(key, default.toRawBits())) } diff --git a/app/src/main/java/com/rtbishop/look4sat/di/UtilityModule.kt b/app/src/main/java/com/rtbishop/look4sat/di/UtilityModule.kt new file mode 100644 index 00000000..afbfd55c --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/di/UtilityModule.kt @@ -0,0 +1,45 @@ +/* + * Look4Sat. Amateur radio and weather satellite tracker and passes predictor for Android. + * Copyright (C) 2019, 2020 Arty Bishop (bishop.arty@gmail.com) + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package com.rtbishop.look4sat.di + +import android.content.Context +import android.content.SharedPreferences +import android.location.LocationManager +import com.rtbishop.look4sat.utility.DataManager +import com.rtbishop.look4sat.utility.PrefsManager +import dagger.Module +import dagger.Provides +import javax.inject.Singleton + +@Module +class UtilityModule { + + @Singleton + @Provides + fun providePrefsManager(preferences: SharedPreferences): PrefsManager { + return PrefsManager(preferences) + } + + @Singleton + @Provides + fun provideDataManager(locationManager: LocationManager, context: Context): DataManager { + return DataManager(locationManager, context) + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt index a67e00e6..efb225ef 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt @@ -103,7 +103,7 @@ class MainActivity : AppCompatActivity() { } private fun setupObservers() { - viewModel.debugMessage.observe(this, Observer { message -> + viewModel.getDebugMessage().observe(this, Observer { message -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show() when (message) { getString(R.string.update_loc_success) -> drawerBinding.drawerBtnLoc.isEnabled = @@ -119,7 +119,7 @@ class MainActivity : AppCompatActivity() { } }) - viewModel.gsp.observe(this, Observer { gsp -> + viewModel.getGSP().observe(this, Observer { gsp -> drawerBinding.drawerLatValue.text = String.format(getString(R.string.pat_location), gsp.latitude) drawerBinding.drawerLonValue.text = diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/MapViewFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/MapViewFragment.kt index 446b7be4..d03e069b 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/MapViewFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/MapViewFragment.kt @@ -82,9 +82,9 @@ class MapViewFragment : Fragment() { } private fun setupComponents() { - val delay = viewModel.delay - gsp = viewModel.gsp.value ?: GroundStationPosition(0.0, 0.0, 0.0) - satPassList = viewModel.satPassList.value ?: emptyList() + val refreshRate = viewModel.getRefreshRate() + gsp = viewModel.getGSP().value ?: GroundStationPosition(0.0, 0.0, 0.0) + satPassList = viewModel.getSatPassList().value ?: emptyList() if (satPassList.isNotEmpty()) { satPassList = satPassList.distinctBy { it.tle } @@ -96,8 +96,8 @@ class MapViewFragment : Fragment() { binding.frameMap.addView(mapView) service.scheduleAtFixedRate( { mapView.invalidate() }, - delay, - delay, + refreshRate, + refreshRate, TimeUnit.MILLISECONDS ) } else { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/PassListFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/PassListFragment.kt index 90e43653..85534f12 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/PassListFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/PassListFragment.kt @@ -97,7 +97,7 @@ class PassListFragment : Fragment() { binding.refLayoutPassList.setColorSchemeResources(R.color.backgroundDark) binding.refLayoutPassList.setOnRefreshListener { calculatePasses() } btnPassPrefs.setOnClickListener { - showSatPassPrefsDialog(viewModel.hoursAhead, viewModel.minEl) + showSatPassPrefsDialog(viewModel.getHoursAhead(), viewModel.getMinElevation()) } binding.fabSatSelect.setOnClickListener { showSelectSatDialog(viewModel.tleMainList, viewModel.tleSelection) @@ -105,7 +105,7 @@ class PassListFragment : Fragment() { } private fun setupObservers() { - viewModel.satPassList.observe(viewLifecycleOwner, Observer { + viewModel.getSatPassList().observe(viewLifecycleOwner, Observer { satPassList = it satPassAdapter.setList(satPassList) if (satPassList.isNotEmpty()) { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/PolarViewFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/PolarViewFragment.kt index 8da12736..992a4325 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/PolarViewFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/PolarViewFragment.kt @@ -78,8 +78,8 @@ class PolarViewFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - viewModel.satPassList.value?.let { - val refreshRate = viewModel.delay + viewModel.getSatPassList().value?.let { + val refreshRate = viewModel.getRefreshRate() satPass = it[args.satPassIndex] mainActivity.supportActionBar?.title = satPass.tle.name diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/adapters/SatPassAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/adapters/SatPassAdapter.kt index 367663a8..b8d4d5f3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/adapters/SatPassAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/adapters/SatPassAdapter.kt @@ -123,7 +123,7 @@ class SatPassAdapter(val viewModel: MainViewModel) : binding.passLeoProgress.progress = satPass.progress itemView.setOnClickListener { - viewModel.satPassList.value?.let { + viewModel.getSatPassList().value?.let { val satPassIndex = it.indexOf(satPass) val action = PassListFragmentDirections.actionPassToPolar(satPassIndex) itemView.findNavController().navigate(action) @@ -148,7 +148,7 @@ class SatPassAdapter(val viewModel: MainViewModel) : String.format(context.getString(R.string.pat_elevation), satPass.pass.maxEl) itemView.setOnClickListener { - viewModel.satPassList.value?.let { + viewModel.getSatPassList().value?.let { val satPassIndex = it.indexOf(satPass) val action = PassListFragmentDirections.actionPassToPolar(satPassIndex) itemView.findNavController().navigate(action) diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/DataManager.kt b/app/src/main/java/com/rtbishop/look4sat/utility/DataManager.kt new file mode 100644 index 00000000..0fe3de22 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/utility/DataManager.kt @@ -0,0 +1,112 @@ +/* + * Look4Sat. Amateur radio and weather satellite tracker and passes predictor for Android. + * Copyright (C) 2019, 2020 Arty Bishop (bishop.arty@gmail.com) + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package com.rtbishop.look4sat.utility + +import android.content.Context +import android.location.LocationManager +import android.util.Log +import com.github.amsacode.predict4java.GroundStationPosition +import com.github.amsacode.predict4java.TLE +import com.rtbishop.look4sat.R +import java.io.FileNotFoundException +import java.io.IOException +import java.io.ObjectInputStream +import java.io.ObjectOutputStream +import javax.inject.Inject + +class DataManager @Inject constructor( + private val locationManager: LocationManager, + private val context: Context +) { + + private val tag = "DataManager" + private val tleMainListFileName = "tleFile.txt" + private val tleSelectionFileName = "tleSelection" + + fun getLastKnownLocation(): GroundStationPosition? { + val passiveProvider = LocationManager.PASSIVE_PROVIDER + var groundStationPosition: GroundStationPosition? = null + return try { + val location = locationManager.getLastKnownLocation(passiveProvider) + location?.let { + groundStationPosition = + GroundStationPosition(it.latitude, it.longitude, it.altitude) + } + groundStationPosition + } catch (e: SecurityException) { + null + } + } + + fun saveSelectionList(selectionList: MutableList) { + try { + val fileOutputStream = + context.openFileOutput(tleSelectionFileName, Context.MODE_PRIVATE) + ObjectOutputStream(fileOutputStream).apply { + writeObject(selectionList) + flush() + close() + } + } catch (exception: IOException) { + } + } + + fun saveTleList(tleList: MutableList) { + try { + val fileOutStream = context.openFileOutput(tleMainListFileName, Context.MODE_PRIVATE) + ObjectOutputStream(fileOutStream).apply { + writeObject(tleList) + flush() + close() + } + } catch (exception: IOException) { + } + } + + @Suppress("UNCHECKED_CAST") + fun loadTleList(): List { + return try { + val tleStream = context.openFileInput(tleMainListFileName) + val tleList = ObjectInputStream(tleStream).readObject() + tleList as List + } catch (exception: FileNotFoundException) { + Log.w(tag, context.getString(R.string.err_no_tle_file)) + emptyList() + } catch (exception: IOException) { + Log.w(tag, exception.toString()) + emptyList() + } + } + + @Suppress("UNCHECKED_CAST") + fun loadSelectionList(): MutableList { + return try { + val selectionStream = context.openFileInput(tleSelectionFileName) + val selectionList = ObjectInputStream(selectionStream).readObject() + selectionList as MutableList + } catch (exception: FileNotFoundException) { + Log.w(tag, context.getString(R.string.err_no_selection_file)) + mutableListOf() + } catch (exception: IOException) { + Log.w(tag, exception.toString()) + mutableListOf() + } + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt new file mode 100644 index 00000000..a93908cb --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/utility/PrefsManager.kt @@ -0,0 +1,92 @@ +/* + * Look4Sat. Amateur radio and weather satellite tracker and passes predictor for Android. + * Copyright (C) 2019, 2020 Arty Bishop (bishop.arty@gmail.com) + * + * 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 2 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, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package com.rtbishop.look4sat.utility + +import android.content.SharedPreferences +import androidx.core.content.edit +import com.github.amsacode.predict4java.GroundStationPosition +import javax.inject.Inject + +class PrefsManager @Inject constructor(private val preferences: SharedPreferences) { + + private val keyHoursAhead = "hoursAhead" + private val keyMinElevation = "minEl" + private val keyLatitude = "latitude" + private val keyLongitude = "longitude" + private val keyAltitude = "altitude" + private val keyRefreshRate = "rate" + + fun getHoursAhead(): Int { + return preferences.getInt(keyHoursAhead, 8) + } + + fun getMinElevation(): Double { + return preferences.getDouble(keyMinElevation, 16.0) + } + + fun getRefreshRate(): Long { + return preferences.getString(keyRefreshRate, "3000")!!.toLong() + } + + fun getGroundStationPosition(): GroundStationPosition { + val lat = preferences.getString(keyLatitude, "0.0")!!.toDouble() + val lon = preferences.getString(keyLongitude, "0.0")!!.toDouble() + val alt = preferences.getString(keyAltitude, "0.0")!!.toDouble() + return GroundStationPosition(lat, lon, alt) + } + + fun setHoursAhead(hours: Int) { + preferences.edit { + putInt(keyHoursAhead, hours) + apply() + } + } + + fun setMinElevation(minEl: Double) { + preferences.edit { + putDouble(keyMinElevation, minEl) + apply() + } + } + + fun setRefreshRate(rate: Long) { + preferences.edit { + putLong(keyRefreshRate, rate) + apply() + } + } + + fun setGroundStationPosition(gsp: GroundStationPosition) { + preferences.edit { + putString(keyLatitude, gsp.latitude.toString()) + putString(keyLongitude, gsp.longitude.toString()) + putString(keyAltitude, gsp.heightAMSL.toString()) + apply() + } + } + + private fun SharedPreferences.Editor.putDouble(key: String, double: Double) { + putLong(key, double.toRawBits()) + } + + private fun SharedPreferences.getDouble(key: String, default: Double): Double { + return Double.fromBits(getLong(key, default.toRawBits())) + } +} diff --git a/build.gradle b/build.gradle index 7d7977d1..fee9d71c 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.0' + classpath 'com.android.tools.build:gradle:3.6.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.2.1" }