kopia lustrzana https://github.com/rt-bishop/Look4Sat
Code separation and cleanup for future testing
rodzic
38b9feb829
commit
b5fa5c0673
|
@ -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<String>()
|
||||
val debugMessage: LiveData<String> = _debugMessage
|
||||
|
||||
private val _satPassList = MutableLiveData<MutableList<SatPass>>()
|
||||
val satPassList: LiveData<MutableList<SatPass>> = _satPassList
|
||||
|
||||
private val _gsp = MutableLiveData<GroundStationPosition>()
|
||||
val gsp: LiveData<GroundStationPosition> = _gsp
|
||||
|
||||
private val urlList = listOf("https://celestrak.com/NORAD/elements/active.txt")
|
||||
|
||||
private val _satPassList = MutableLiveData<MutableList<SatPass>>()
|
||||
private val _debugMessage = MutableLiveData<String>()
|
||||
private val _gsp = MutableLiveData<GroundStationPosition>()
|
||||
private var calculationJob: Job? = null
|
||||
|
||||
@Inject
|
||||
lateinit var locationManager: LocationManager
|
||||
@Inject
|
||||
lateinit var preferences: SharedPreferences
|
||||
@Inject
|
||||
lateinit var repository: Repository
|
||||
|
||||
lateinit var tleMainList: List<TLE>
|
||||
lateinit var tleSelection: MutableList<Int>
|
||||
@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<GroundStationPosition> = _gsp
|
||||
fun getDebugMessage(): LiveData<String> = _debugMessage
|
||||
fun getSatPassList(): LiveData<MutableList<SatPass>> = _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<Int>) {
|
||||
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<SatPass>()
|
||||
val dateNow = Date()
|
||||
val dateFuture = Calendar.getInstance().let {
|
||||
it.time = dateNow
|
||||
it.add(Calendar.HOUR, hoursAhead)
|
||||
it.time
|
||||
}
|
||||
var passList = mutableListOf<SatPass>()
|
||||
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<SatPass>,
|
||||
hoursAhead: Int
|
||||
): MutableList<SatPass> {
|
||||
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<Transmitter> {
|
||||
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<TLE>
|
||||
} 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<Int>
|
||||
} 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()))
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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 =
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<Int>) {
|
||||
try {
|
||||
val fileOutputStream =
|
||||
context.openFileOutput(tleSelectionFileName, Context.MODE_PRIVATE)
|
||||
ObjectOutputStream(fileOutputStream).apply {
|
||||
writeObject(selectionList)
|
||||
flush()
|
||||
close()
|
||||
}
|
||||
} catch (exception: IOException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun saveTleList(tleList: MutableList<TLE>) {
|
||||
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<TLE> {
|
||||
return try {
|
||||
val tleStream = context.openFileInput(tleMainListFileName)
|
||||
val tleList = ObjectInputStream(tleStream).readObject()
|
||||
tleList as List<TLE>
|
||||
} 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<Int> {
|
||||
return try {
|
||||
val selectionStream = context.openFileInput(tleSelectionFileName)
|
||||
val selectionList = ObjectInputStream(selectionStream).readObject()
|
||||
selectionList as MutableList<Int>
|
||||
} catch (exception: FileNotFoundException) {
|
||||
Log.w(tag, context.getString(R.string.err_no_selection_file))
|
||||
mutableListOf()
|
||||
} catch (exception: IOException) {
|
||||
Log.w(tag, exception.toString())
|
||||
mutableListOf()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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()))
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue